2016-01-25 2 views
2

Я хочу проанализировать выражение SQL, которое содержит и or ключевых слов. Проблема в Antlrwork может генерировать исключение для грамматики ошибок, но сгенерированный код Java не может генерировать исключение. Между тем, я обнаружил, что сгенерированный код java - это ошибка, которая может генерировать только половину AST и не содержит информации об ошибках, которые не могут достичь пути исключения.Для исключения ANTLR3, antlrworks может работать, но сгенерированный код java не может работать

Это моя точка г файлы:

grammar ContainsExpr; 

    options { 
     language = Java; 
     output=AST; 
     ASTLabelType=CommonTree; 
    } 

    tokens { 
     DIVIDE = '/' ; 
     PLUS = '+' ; 
     MINUS = '-' ; 
     STAR = '*' ; 
     MOD = '%' ; 

     AMPERSAND = '&' ; 
     TILDE = '~' ; 
     BITWISEOR = '|' ; 
     COMMA = ','; 
     DOT = '.'; 
     LPAREN = '(' ; 
     RPAREN = ')' ; 

     EQUAL = '='; 
     NOTEQUAL = '!='; 
     LESSTHANOREQUALTO = '<='; 
     LESSTHAN = '<'; 
     GREATERTHANOREQUALTO = '>='; 
     GREATERTHAN = '>'; 

     AND = 'AND'; 
     OR = 'OR' ; 
     TRUE = 'TRUE'; 
     FALSE = 'FALSE'; 
     KW_NEAR = 'NEAR'; 
     DOUBLE_QUOTE = '\"'; 
     SINGLE_QUOTE = '\''; 

     TOK_NEAR; 
     TOK_ITEMS; 
     TOK_PARAMETER; 
     TOK_WILDCARDS; 
    } 

    @header { 
    package test1; 
    } 

    @members { 

     //override method 
     public void reportError(RecognitionException e) { 
     displayRecognitionError(this.getTokenNames(), e); 
     } 

    @Override 
     public void emitErrorMessage(String message) { 
     throw new RuntimeException(message); 
     } 
    } 

    @lexer::header { 
    package test1; 
    } 

    @lexer::members { 

     //override method 
     public void reportError(RecognitionException e) { 
     displayRecognitionError(this.getTokenNames(), e); 
     } 
    } 

    @rulecatch { 
     catch (RecognitionException e) { 
      reportError(e); 
      throw e; 
     } 
    } 

    // LITERALS 
    fragment 
    Letter 
     : 'a'..'z' | 'A'..'Z' 
     ; 

    fragment 
    Digit 
     : 
     '0'..'9' 
     ; 

    fragment 
    Exponent 
     : 
     ('e' | 'E') (PLUS|MINUS)? (Digit)+ 
     ; 

    Number 
     : 
     (Digit)+ (DOT (Digit)* (Exponent)? | Exponent)? 
     ; 

    fragment 
    UnquotedString 
     : 
      (~(SINGLE_QUOTE|DOUBLE_QUOTE|' '|'\t'|'\n'|LPAREN|RPAREN|COMMA))+ 
     ; 

    fragment 
    QuotedLiteral 
     : 
     DOUBLE_QUOTE (~(DOUBLE_QUOTE|'\\') | ('\\' .))* DOUBLE_QUOTE 
     ; 

    Parameter 
     : 
     UnquotedString | QuotedLiteral 
     ; 

    WS : (' '|'\r'|'\t'|'\n'|'\u000C')* {$channel=HIDDEN;} 
     ; 

    eval 
     : 
     searchCondition 
     ; 

    //AND has precedence over OR  
    searchCondition 
     : 
     andExpr (precedenceOrOperator^ andExpr)* 
     ; 

    andExpr 
     : 
     subCondition (precedenceAndOperator^ subCondition)* 
     ; 

    precedenceAndOperator 
     : 
     AND | AMPERSAND 
     ; 

    precedenceOrOperator 
     : 
     OR | BITWISEOR 
     ; 

    subCondition 
     : 
      atom 
     | LPAREN searchCondition RPAREN 
     ; 

    atom 
     : 
     subEressixpon  
     ; 

    subEressixpon 
     : 
      Parameter -> ^(TOK_PARAMETER Parameter) 
     ; 

При вводе неправильно выражение expr1 epxr2 (The И пропускается), результат выполнения кода Java является "выражение1".

Сгенерированный Java код searchCondition правило неверно:

try { 
      // (andExpr (precedenceOrOperator^andExpr)*) 
      // andExpr (precedenceOrOperator^andExpr)* 
      { 
      root_0 = (CommonTree)adaptor.nil(); 


      pushFollow(FOLLOW_andExpr_in_searchCondition714); 
      andExpr2=andExpr(); 
      state._fsp--; 

      adaptor.addChild(root_0, andExpr2.getTree()); 

      // (precedenceOrOperator^andExpr)* 
      loop1: 
      while (true) { 
       int alt1=2; 
       int LA1_0 = input.LA(1); 
       if ((LA1_0==BITWISEOR||LA1_0==OR)) { 
        alt1=1; 
       } 

       switch (alt1) { 
       case 1 : 
        // precedenceOrOperator^andExpr 
        { 
        pushFollow(FOLLOW_precedenceOrOperator_in_searchCondition717); 
        precedenceOrOperator3=precedenceOrOperator(); 
        state._fsp--; 

        root_0 = (CommonTree)adaptor.becomeRoot(precedenceOrOperator3.getTree(), root_0); 
        pushFollow(FOLLOW_andExpr_in_searchCondition720); 
        andExpr4=andExpr(); 
        state._fsp--; 

        adaptor.addChild(root_0, andExpr4.getTree()); 

        } 
        break; 

       default : 
        break loop1; 
       } 
      } 

      } 

      retval.stop = input.LT(-1); 

      retval.tree = (CommonTree)adaptor.rulePostProcessing(root_0); 
      adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop); 

     } 

      catch (RecognitionException e) { 
       reportError(e); 
       throw e; 
      } 

     finally { 
      // do for sure before leaving 
     } 

В while петля, Когда LA1_0 является OR ключевые слова, это будет нормально достигают точки исключения. Таким образом, он не сможет выбросить исключение.

+0

Пожалуйста, напишите полную грамматику. Здесь отсутствуют правила лексера (например,AMPERSAND) – Rainer

+0

Пожалуйста, отметьте мой ответ как решающий (если это так) или опубликуйте обновления, которые по-прежнему являются проблемой для вас. – Rainer

+0

@Rainer. Проблема не в том, чтобы получить исключение сгенерированным кодом Java, но antlrworks и плагин eclipse из anltr3 могут исключение при неверном вводе интерпретатора. – sol

ответ

2

Прошло некоторое время с тех пор, как я работал с antlr, но вы можете посмотреть здесь.

How Get error messages of antlr parsing?

Вы можете получить сообщения об ошибках синтаксического анализа.

Надеюсь, это поможет. Cheers

1

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

Я изменил 3 вещи:

  1. поставил правила LeXeR ПОСЛЕ правил синтаксического анализа
  2. Добавлено символ EOF на вашем верхнем уровне правила синтаксического анализатора
  3. переопределить только необходимые два метода «ReportError» парсер и лексического

весело и продолжает спрашивать ^^

grammar ContainsExpr; 

    options { 
     language = Java; 
     output=AST; 
     ASTLabelType=CommonTree; 
    } 

    tokens { 
     DIVIDE = '/' ; 
     PLUS = '+' ; 
     MINUS = '-' ; 
     STAR = '*' ; 
     MOD = '%' ; 

     AMPERSAND = '&' ; 
     TILDE = '~' ; 
     BITWISEOR = '|' ; 
     COMMA = ','; 
     DOT = '.'; 
     LPAREN = '(' ; 
     RPAREN = ')' ; 

     EQUAL = '='; 
     NOTEQUAL = '!='; 
     LESSTHANOREQUALTO = '<='; 
     LESSTHAN = '<'; 
     GREATERTHANOREQUALTO = '>='; 
     GREATERTHAN = '>'; 

     AND = 'AND'; 
     OR = 'OR' ; 
     TRUE = 'TRUE'; 
     FALSE = 'FALSE'; 
     KW_NEAR = 'NEAR'; 
     DOUBLE_QUOTE = '\"'; 
     SINGLE_QUOTE = '\''; 

     TOK_NEAR; 
     TOK_ITEMS; 
     TOK_PARAMETER; 
     TOK_WILDCARDS; 
    } 

    @header { 
    package test1; 
    } 

    @lexer::header { 
    package test1; 
    } 

    @parser::members { 
     @Override 
     public void reportError(RecognitionException e) { 
     throw new RuntimeException("I quit!\n" + e.getMessage()); 
     } 
    } 

    @lexer::members { 
     @Override 
     public void reportError(RecognitionException e) { 
     throw new RuntimeException("I quit!\n" + e.getMessage()); 
     } 
    } 

    eval 
     : 
     searchCondition EOF 
     ; 

    //AND has precedence over OR  
    searchCondition 
     : 
     andExpr (precedenceOrOperator^ andExpr)* 
     ; 

    andExpr 
     : 
     subCondition (precedenceAndOperator^ subCondition)* 
     ; 

    precedenceAndOperator 
     : 
     AND | AMPERSAND 
     ; 

    precedenceOrOperator 
     : 
     OR | BITWISEOR 
     ; 

    subCondition 
     : 
      atom 
     | LPAREN searchCondition RPAREN 
     ; 

    atom 
     : 
     subEressixpon  
     ; 

    subEressixpon 
     : 
      Parameter -> ^(TOK_PARAMETER Parameter) 
     ; 

    // LITERALS 
    fragment 
    Letter 
     : 'a'..'z' | 'A'..'Z' 
     ; 

    fragment 
    Digit 
     : 
     '0'..'9' 
     ; 

    fragment 
    Exponent 
     : 
     ('e' | 'E') (PLUS|MINUS)? (Digit)+ 
     ; 

    Number 
     : 
     (Digit)+ (DOT (Digit)* (Exponent)? | Exponent)? 
     ; 

    fragment 
    UnquotedString 
     : 
      (~(SINGLE_QUOTE|DOUBLE_QUOTE|' '|'\t'|'\n'|LPAREN|RPAREN|COMMA))+ 
     ; 

    fragment 
    QuotedLiteral 
     : 
     DOUBLE_QUOTE (~(DOUBLE_QUOTE|'\\') | ('\\' .))* DOUBLE_QUOTE 
     ; 

    Parameter 
     : 
     UnquotedString | QuotedLiteral 
     ; 

    WS : (' '|'\r'|'\t'|'\n'|'\u000C')* {$channel=HIDDEN;} 
     ; 

Вот мой маленький тест

package test1; 

import junit.framework.TestCase; 

import org.antlr.runtime.ANTLRStringStream; 
import org.antlr.runtime.CommonTokenStream; 
import org.antlr.runtime.TokenStream; 
import org.junit.Assert; 

public class Test extends TestCase { 

    public void test() { 
     String test = "expr1 epxr2"; // AND missing 

     ANTLRStringStream input = new ANTLRStringStream(test); 
     TokenStream tokens = new CommonTokenStream(new ContainsExprLexer(input)); 
     ContainsExprParser parser = new ContainsExprParser(tokens); 

     try { 
      parser.eval(); 
      Assert.fail("Should throw Exception"); 
     } catch (Exception e) { 
      //jippi 
      System.out.println(e); 
     } 
    } 
} 

С результатом

java.lang.RuntimeException: I quit! 
null 

UPDATE

Я нашел себя часть моего ответа здесь ANTLR not throwing errors on invalid input

+0

привет, вы должны распечатать трассировку стека. «Null» не является исключением указателя. «RecognitionException» не имеет метода getMessage(). – sol

+0

Ну, в реальном приложении я бы, конечно, использовал фреймворк регистрации для обработки исключения. Это было просто доказательством концепции. Пожалуйста, отметьте, как было решено, если да. спасибо Я только что скопировал блок исключений из другого ответа, с которым я связался. Вы должны просто обернуть исключение в новом RuntimeException («...», e) – Rainer

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