2016-07-28 10 views
3

Строка:Java: какой синтаксический анализатор лучше всего подходит для текста в соответствии с парами скобок? Пример

«(Это уровень 1. (Это уровень 2. (Это уровень 3) Вернуться к уровню 2.) Перейти к уровню 1)»

Если это не так заранее известно, сколько уровней будет круглых скобок (т. е. в Уровне 3 может быть уровень 4, 5, 6 и т. д.), я понимаю, что регулярное выражение не может соответствовать тексту Уровня 2 в приведенном выше пример. Таким образом, в этом примере, это не было бы возможным, чтобы соответствовать следующим используя регулярные выражения:

«(Это уровень 2. (Это уровень 3) Назад к уровню 2)»

Я прочитал об использовании парсера для этого, но я не уверен, что лучше. Я бы хотел упростить использование, скорость и совместимость с Java. Любая помощь по этому поводу будет оценена по достоинству.

+0

Вы хотите иметь возможность сопоставлять определенные уровни вложенных круглых скобок? Как обеспечить вложенный уровень и получить шаблон динамически? –

+0

Какова ваша конечная цель, то есть какой вы хотите, чтобы ваш результат был? – NitroNbg

+1

См. Https://ideone.com/RP76IO. Однако немного другой подход к определению уровня. –

ответ

4

Я сделал что-то подобное в прошлом году.

Это было легко, вы начинаете с поиска последних (, и вы храните индекс. Затем вы просматриваете первый ) после сохранения индекса. Вам просто нужна подстрока для извлечения текста между этими двумя указательными и сделал :)

Для следующего уровня, использовать предыдущий индекс для поиска предыдущего/следующей (/) и у вас есть простой парсер;)

Вот пример простого кода для печати каждого уровня:

public static void main(String... args) { 
     String s = "(This is level 1. (This is level 2. (This is level 3.) Back to level 2.) Back to level 1.)"; 
     searchInto(s); 
    } 

    public static void searchInto(String s){ 
     searchInto(s, s.length(), 0); 
    } 

    public static void searchInto(String s, int from, int to){ 
     int nextOpen = s.lastIndexOf("(", from-1); 
     if(nextOpen >= 0){ 
      int nextClose = s.indexOf(")", to); 

      System.out.println(s.substring(nextOpen + 1, nextClose)); 
      searchInto(s, nextOpen, nextClose + 1); 
     } else 
      return; 
    } 

Напечатает:

This is level 3. 
This is level 2. (This is level 3.) Back to level 2. 
This is level 1. (This is level 2. (This is level 3.) Back to level 2.) Back to level 1. 

EDIT:

Это должно покрывать больше земли. Это будет искать внутренний блок AND и рядом друг с другом.

public static void main(String... args) { 
     searchInto("(This is level 1. (This is level 2. (This is level 3.) Back to level 2.) Back to level 1.)"); 
     searchInto("(L1) (L2) (L3)"); 
     searchInto("(L1) (L2 (L2a)) (L3)"); 
    } 

    public static void searchInto(String s){ 
     searchInto(s, s, s.length(), 0); 
    } 

    public static void searchInto(String s, String original, int from, int to){ 
     int nextOpen = s.lastIndexOf("(", from); 
     if(nextOpen >= 0){ 
      int nextClose = s.indexOf(")", nextOpen); 
      String tmp = original.substring(nextOpen + 1, nextClose); 
      System.out.println(tmp); //Print the result, use a List to store or treat it directly. 
      s = s.substring(0, nextOpen) + "#" + s.substring(nextOpen + 1, nextClose) + "#" + s.substring(nextClose + 1); 
      searchInto(s, original, nextOpen - 1, nextClose + 1); 
     } else 
      return; 
    } 

Выведет:

This is level 3. 
This is level 2. (This is level 3.) Back to level 2. 
This is level 1. (This is level 2. (This is level 3.) Back to level 2.) Back to level 1. 

L3 
L2 
L1 

L3 
L2a 
L2 (L2a) 
L1 

При использовании альтернативной строки для замены уже нашли характер, предотвратить код застрять по индексу. Но я печатаю значение из оригинала, чтобы напечатать правильное значение (без знака #, который использовался для замены найденного ())

Это немного дороже, так что это действительно так, если вам нужно покрыть каждую структуру.

+1

Но это не будет работать со строками типа «(Lvl1 (Lvl2) Lvl1 (lvl2bis) Lvl1)» –

+0

Его пример и пояснение не указывают этот тип рисунка, но с небольшим количеством времени это могло бы работать (я сделал это давно, нужно запомнить путь;)) – AxelH

+2

@ JérèmLeBlond, см. мое редактирование, это сделает это. – AxelH

1

Это должно работать со строками, как это "(lvl1 (LVL2) lvl1 (lvl2bis) lvl1)":

private static void printLevels(String in) { 
    List<String> levels = new ArrayList<>(); 
    List<Integer> indexes = new ArrayList<>(); 
    for (int i = 0; i < in.length(); i++) { 
     if (in.charAt(i) == '(') { 
      indexes.add(i); 
     } else if (in.charAt(i) == ')') { 
      levels.add(in.substring(indexes.remove(indexes.size()-1), i+1)); 
     } 
    } 
    for (String string : levels) { 
     System.out.println(string); 
    } 
} 

Это:

String in = "(Lvl1 (Lvl2) Lvl1 (lvl2bis) Lvl1)"; 
printLevels(in); 

Напечатает:

(Lvl2) 
(lvl2bis) 
(Lvl1 (Lvl2) Lvl1 (lvl2bis) Lvl1) 

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

  • Нет связанных вопросов^_^