2015-03-25 1 views
1

Я хочу заменить скобки в строке, пока табуляция и добавление новых строк, как довольно печатная версия.Как заменить скобки(), сохранить содержимое и вставить результат в Java?

(foo) AND ((bar) OR (baz)) 

становится

 (
      foo 
    ) 
AND 
    (
      (
       bar 
     ) 
    OR 
      (
      baz 
     ) 
    ) 

Я попытался:

"((foo) OR ((bar)(baz)))".replaceAll("\\((.*?)\\)", "\\(\n\t$1\n\\)") 

но это не совсем работает.

+5

Грамматика вашего выражения в скобках не является регулярной, поэтому вы не можете использовать регулярное выражение для синтаксического анализа и изменения его * в соответствии с его синтаксисом *. Возможно, вам придется написать парсер, например. один из которых использует рекурсивный спуск или аналогичный. – laune

+0

Не пытайтесь разбирать нерегулярные вещи с регулярными выражениями, или [это] (http://stackoverflow.com/a/1732454/1361506) произойдет с вами. – azurefrog

ответ

1

laune azurefrog имеют право. Выражение, предоставленное вами, не является регулярным, поэтому вы не можете использовать обычный механизм выражения для префикса выражения. На мой взгляд, лучшее, что вы можете сделать, это написать парсер, который может справиться с этой задачей. Я всегда пытаюсь отделить логику парсера от кода, связанного с бизнесом. Вы можете заметить, что логика, которая касается форматирования мест в реализации ExpressionListener. Ниже вы можете найти код.

public class PrettyPrintExample { 

    private interface ExpressionListener { 

     void lb(); 

     void rb(); 

     void content(String content); 

    } 

    private enum Type { 
     LB, RB, STRING, END 
    } 

    private static class Token { 
     Type type; 
     String value; 

     public Token(Type type, String value) { 
      super(); 
      this.type = type; 
      this.value = value; 
     } 

     @Override 
     public String toString() { 
      return "Token [type=" + type + ", value=" + value + "]"; 
     } 
    } 

    private static class Lexer { 

     private int current; 
     private String input; 

     public Lexer(String input) { 
      this.input = input; 
     } 

     private char getChar() { 
      return input.charAt(current++); 
     } 

     private void unputChar() { 
      current--; 
     } 

     private boolean hasNextChar() { 
      return current < input.length(); 
     } 

     Token next() { 

      if (!hasNextChar()) { 
       return new Token(Type.END, ""); 
      } 

      char c = getChar(); 

      while (Character.isWhitespace(c)) { 
       c = getChar(); 
      } 

      if (c == '(') { 
       return new Token(Type.LB, "("); 
      } 

      if (c == ')') { 
       return new Token(Type.RB, ")"); 
      } 

      unputChar(); 

      StringBuilder buffer = new StringBuilder(); 
      while (hasNextChar()) { 

       c = getChar(); 

       if (c != '(' && c != ')' && !Character.isWhitespace(c)) { 
        buffer.append(c); 
       } else { 
        unputChar(); 
        break; 
       } 

      } 

      return new Token(Type.STRING, buffer.toString()); 

     } 
    } 

    private static Lexer lexer; 
    private static Token currentToken; 

    public static void parse(String line, ExpressionListener listener) { 
     lexer = new Lexer(line); 
     currentToken = lexer.next(); 
     expression(listener); 
     consume(Type.END); 
    } 

    private static void expression(ExpressionListener listener) { 

     while (true) { 

      if (match(Type.STRING)) { 
       listener.content(currentToken.value); 
       consume(Type.STRING); 
      } else if (match(Type.LB)) { 
       consume(Type.LB); 
       listener.lb(); 
       expression(listener); 
       consume(Type.RB); 
       listener.rb(); 
      } else { 
       break; 
      } 

     } 

    } 

    private static boolean match(Type type) { 
     return type == currentToken.type; 
    } 

    private static void consume(Type type) { 
     if (!match(type)) { 
      throw new RuntimeException(String.format("Should be %s is %s", type.name(), currentToken.type.name())); 
     } 
     currentToken = lexer.next(); 
    } 

    public static void main(String[] args) { 
     String line = "(foo) AND ((bar) OR (baz))"; 
     parse(line, new ExpressionListener() { 

      private int indent = 0; 

      private void indent(int indent) { 
       StringBuilder builder = new StringBuilder(); 
       for (int i = 0; i < indent; i++) { 
        builder.append("\t"); 
       } 
       System.out.print(builder.toString()); 
      } 

      private void nl() { 
       System.out.println(); 
      } 

      @Override 
      public void lb() { 
       indent(++indent); 
       System.out.print("("); 
       nl(); 
      } 

      @Override 
      public void rb() { 
       indent(indent); 
       System.out.print(")"); 
       indent--; 
       nl(); 
      } 

      @Override 
      public void content(String content) { 
       indent(indent); 
       System.out.print(content); 
       nl(); 
      } 
     }); 

    } 

} 

выход

(
    foo 
    ) 
AND 
    (
     (
     bar 
     ) 
    OR 
     (
     baz 
     ) 
    ) 

Я знаю, что использование КЛЛ парсер для вашего случая не является простейшим возможным решением, но имейте в виду, что если Ваше выражение станет намного сложным было бы очень легко продлить синтаксический анализатор.

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