2017-01-25 4 views
0

Я создаю интерфейс разметки Markdown-esque. Например, когда пользователь вводит **example string**, регулярное выражение используется для поиска двух вхождений ** (определение полужирного текста), а фактический открытый текст будет изменен на <b>**example string**</b> и отображен как HTML.Алгоритм для вставки строки на основе правил нескольких регулярных выражений

Это мое мышление для разбора ввода пользователя в HTML:

  1. Для каждого правила в правилах регулярных выражений
  2. Для каждого вхождения start pattern (текущего правила регулярных выражений)
  3. Возьмите весь текст после конец start pattern (назовем эту start substring)
  4. Для первого экземпляра end pattern в start substring
  5. Возьмите substring(start_match.start() + end_match.end()) из текста
  6. Append его первоначально пустой final text строки
  7. отбраковки оставшийся текст с помощью substring(start_match.start() + end_match.end()), кормить это обратно в текст читать на 2.

Мой код:

public static String process(String input_text) { 
    String final_text = ""; 
    String current_text = input_text; 

    for (MarkdownRule rule : _rules) { 
     Pattern s_ptrn = rule.getStartPattern(); // Start pattern 
     Pattern e_ptrn = rule.getEndPattern();  // End pattern 

     /* For each occurrence of the start pattern */ 
     Matcher s_matcher = s_ptrn.matcher(current_text); 
     while (s_matcher.find()) { 
      int s_end = s_matcher.end(); 
      int s_start = s_matcher.start(); 

      /* Take all text after the end of start match */ 
      String working_text = current_text.substring(s_end); // ERROR HERE 

      /* For first instance of end pattern in remaining text */ 
      Matcher e_matcher = e_ptrn.matcher(working_text); 
      if (e_matcher.find()) { 

       /* Take full substring from current text */ 
       int e_end = e_matcher.end(); 
       working_text = current_text.substring(s_start, s_end + e_end); 

       /* Append to final text */ 
       working_text = new StringBuilder(working_text).insert(0, "<b>").append("</b>").toString(); 
       final_text = new StringBuilder(final_text).append(working_text).toString(); 

       /* Remove working text from current text */ 
       current_text = new StringBuilder(current_text).substring(s_start + e_end); 
      } 
     } 
    } 

    return final_text; 
} 

Хотя теоретически это должно работать нормально, я получаю StringIndexOutOfBoundsException на этой линии:

/* Take all text after the end of start match */ 
String working_text = current_text.substring(s_end); 

Когда я использую текст ввода **example**. Я считаю, что он отлично работает для первого появления start pattern (по индексам 0 & 1), но затем строка не получается правильно отбраковаться, и цикл затем вызывается в текстовом поле **, что дает ошибку вне диапазона. (Я не могу этого гарантировать, хотя - это то, что я считаю из собственного тестирования)

К сожалению, мое устранение неполадок не могло устранить ошибку. Заранее благодарю за любую помощь.

+1

Зачем придумывать свои собственные, если есть уже уценка?!?! – mb21

+0

Я хочу управлять им в реальном времени, подобно приложениям типа Typora. Также просто посмотреть, могу ли я! – user3668541

+0

не уверен, что в реальном времени или нет имеет отношение к синтаксису и синтаксическим анализаторам ... но обратите внимание, что авторы синтаксического анализатора выучили трудный путь: на основе вашего парсера в регулярном выражении не существует долгосрочной стратегии. См. Https: // github .com/jgm/CommonMark для современной реализации. – mb21

ответ

1

Вы меняете (усадка) current_text

/* Remove working text from current text */ 
current_text = new StringBuilder(current_text).substring(s_start + e_end); 

, а сличитель сохранил первоначальную current_text строку, которая не изменяется, независимо от того, что вы делаете, чтобы current_text впоследствии.

/* For each occurrence of the start pattern */ 
Matcher s_matcher = s_ptrn.matcher(current_text); 

Для новой строки вам понадобится новый матчи.

+0

Ah - поэтому 'Matcher' кэширует строковое значение, а не ссылается на экземпляр. Это интересно (и немного раздражает). Спасибо! – user3668541

+1

Это не совсем правильно. 'Matcher' ловит ** ссылку ** на экземпляр' String'.Поскольку 'String' является неизменным объектом, вы не можете изменить значение String, но вы можете ссылаться на ** новую **' String'. И это то, что происходит, когда вы меняете 'current_text'. Вы в основном ссылаетесь на ** новую ** 'String', в то время как' Matcher' все еще ссылается на старую 'String'. – SlumpA

Смежные вопросы