java - 如何检测用户是否输入了不符合我的ANTLR语法规则的字符串?

标签 java error-handling antlr4

我正在制作一个计算机代数系统,它将采用代数表达式并将其简化或区分。

如下面的代码所示,用户输入已被接受,但是如果它是不符合我的语法规则的字符串,则错误,
第1:6行出现不匹配的输入'',期望{'(',INT,VAR},并且程序继续运行。

如何捕获错误并停止程序运行?预先感谢您的任何帮助。

Controller 类:

    public static void main(String[] args) throws IOException {
        String userInput = "x*x*x+";
        getAST(userInput);

    }

    public static AST getAST(String userInput) {
        ParseTree tree = null;
        ExpressionLexer lexer = null;
        ANTLRInputStream input = new ANTLRInputStream(userInput);
        try {
        lexer = new ExpressionLexer(input);
        }catch(Exception e) {
            System.out.println("Incorrect grammar");
        }
        System.out.println("Lexer created");

        CommonTokenStream tokens = new CommonTokenStream(lexer);
        System.out.println("Tokens created");
        ExpressionParser parser = new ExpressionParser(tokens);
        System.out.println("Tokens parsed");


        tree = parser.expr(); 

        System.out.println("Tree created");
        System.out.println(tree.toStringTree(parser)); // print LISP-style tree
        Trees.inspect(tree, parser);

        ParseTreeWalker walker = new ParseTreeWalker();
        ExpressionListener listener = new buildAST();
        walker.walk(listener, tree);

        listener.printAST();
        listener.extractExpression();

        return new AST();
    }
}

我的语法:
grammar Expression;

@header {
package exprs;

}
@members {
    // This method makes the parser stop running if it encounters
    // invalid input and throw a RuntimeException.
    public void reportErrorsAsExceptions() {
        //removeErrorListeners();

        addErrorListener(new ExceptionThrowingErrorListener());
    }

    private static class ExceptionThrowingErrorListener extends BaseErrorListener {
        @Override
        public void syntaxError(Recognizer<?, ?> recognizer,
                Object offendingSymbol, int line, int charPositionInLine,
                String msg, RecognitionException e) {
            throw new RuntimeException(msg);
        }
    }
}
@rulecatch {
    // ANTLR does not generate its normal rule try/catch
    catch(RecognitionException e) {
        throw e;
    }
}

expr  : left=expr op=('*'|'/'|'^') right=expr 
      | left=expr op=('+'|'-') right=expr 
      | '(' expr ')' 
      | atom 
      ;

atom : INT|VAR;
INT   : ('0'..'9')+ ;
VAR   : ('a' .. 'z') | ('A' .. 'Z') | '_';

WS    : [ \t\r\n]+ -> skip ;

最佳答案

ANTLR4的典型解析运行包括两个阶段:

  • 使用SLL预测模式运行的“快速处理”,可根据发现的第一个语法错误提供帮助。
  • 使用LL预测模式的常规运行,尝试从解析器错误中恢复。仅在第一步出错时才需要执行此第二步。

  • 第一步是一个宽松的解析运行,它不能解决某些歧义,因此可以报告一个实际上不存在的错误(在LL模式下解决时)。但是第一步要更快,并且为语法正确的输入提供更快的结果。此(JS)代码显示了设置:
        this.parser.removeErrorListeners();
        this.parser.addErrorListener(this.errorListener);
    
        this.parser.errorHandler = new BailErrorStrategy();
        this.parser.interpreter.setPredictionMode(PredictionMode.SLL);
    
        try {
            this.tree = this.parser.grammarSpec();
        } catch (e) {
            if (e instanceof ParseCancellationException) {
                this.tokenStream.seek(0);
                this.parser.reset();
                this.parser.errorHandler = new DefaultErrorStrategy();
                this.parser.interpreter.setPredictionMode(PredictionMode.LL);
                this.tree = this.parser.grammarSpec();
            } else {
                throw e;
            }
        }
    

    为了避免在第一步中尝试解决语法错误,还必须设置BailErrorStrategy。如果发生语法错误,此策略只会抛出ParseCancellationException(类似于您在代码中所做的操作)。您可以在catch子句中添加您自己的处理,以询问用户正确的输入并重新旋转解析步骤。

    关于java - 如何检测用户是否输入了不符合我的ANTLR语法规则的字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55746530/

    相关文章:

    java - 如何有效区分ANTLR4规则中的不同标记?

    java - antlr 4 无法作为词法分析器或解析器加载

    java - 验证正则表达式

    java - 如何为 JTree 中的特定节点调用 DefaultTreeCellRenderer

    python - 如何打印嵌套循环的异常?

    python - ViewDoesNotExist : Error

    antlr - 从解析器切换 Antlr 词法分析器模式

    java - 如何使用 Java API 创建 PlantUML 图而不使用 PlantUML 图代码?

    java - 在方法中同时读取路径参数和 json 正文请求

    javascript - 语法错误: missing ) after argument list in google script while i was creating event from GoogleAppsScript to Google Calendar