对于ANTLR3异常,antlrworks可以工作,但生成的java代码无法工作

对于ANTLR3异常,antlrworks可以工作,但生成的java代码无法工作,java,antlr,antlr3,Java,Antlr,Antlr3,我想解析包含和和或关键字的SQL表达式。问题是Antlrwork可以为错误语法抛出异常,但生成的java代码不能抛出异常。同时,我发现生成的java代码是一个错误,只能生成AST的一半,并且没有错误信息,执行路径无法到达异常点 这是我的dot g文件: grammar ContainsExpr; options { language = Java; output=AST; ASTLabelType=CommonTree; } to

我想解析包含
关键字的SQL表达式。问题是
Antlrwork
可以为错误语法抛出异常,但生成的java代码不能抛出异常。同时,我发现生成的java代码是一个错误,只能生成AST的一半,并且没有错误信息,执行路径无法到达异常点

这是我的dot g文件:

 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) 
        ;

while
循环中,当
LA1_0
关键字时,它将是异常的正常到达点。所以不能抛出异常。

我已经有一段时间没有使用antlr了,但您可以在这里查看一下

您可以从解析器获取错误消息


希望这有帮助。干杯

好的,我可以先确认一下你的问题,但经过一点尝试后,它成功了

我改变了三件事:

  • 将lexer规则放在解析器规则之后
  • 在顶级解析器规则中添加了EOF符号
  • 仅重写解析器和lexer中所需的两个方法“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;}
            ;
    
    结果

    java.lang.RuntimeException: I quit!
    null
    
    更新

    我发现自己是我答案的一部分

    请张贴完整的语法。这里缺少lexer规则(例如,符号),请将我的答案标记为解决问题的答案(如果是),或者发布更新,说明仍然存在的问题you@Rainer问题是生成的java代码无法获取异常,但是ANLTRWorks和anltr3的eclipse插件在解释器输入错误时都会引发异常。我想你可以在语法中提供一些选项来修改lexer和parser的行为啊,我刚刚想到一件事。若我没记错的话,你们可能想看看EOF标记,并将其添加到顶级解析器规则的末尾。它实际上只是一个很轻的内存,但EOF令牌和异常处理之间有某种关联。嗨,你们应该打印异常的堆栈跟踪。
    null
    不是指针异常。
    RecognitionException
    没有
    getMessage()方法。这只是一个概念的证明。如果是,请标记为已解决。谢谢,我刚刚从我链接到的另一个答案复制了异常块。您应该将异常包装到新的RuntimeException(“…”,e)中
    
    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