我正在制作一个计算机代数系统,它将采用代数表达式并将其简化或区分。
如下面的代码所示,用户输入已被接受,但是如果它是不符合我的语法规则的字符串,则错误,
第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的典型解析运行包括两个阶段:
第一步是一个宽松的解析运行,它不能解决某些歧义,因此可以报告一个实际上不存在的错误(在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/