gpt4 book ai didi

java - Antlr 处理异常

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:25:47 24 4
gpt4 key购买 nike

我已经使用 AST 树使用 Antlr 3 开发了一个复杂的语法。 ANTLR 生成 Lexer 和 Parser。问题是,当用户输入无效的语法时,例如,语法需要“;”。用户没有输入此内容,然后在我的 Eclipse IDE 中出现以下异常:

 line 1:24 mismatched input '<EOF>' expecting ';'

这个Exception怎么处理,因为我 try catch 这个Exception,但是没有捕获到Exception。这是一个异常(exception)吗?我似乎不明白为什么没有捕获到这个异常。我试图找出答案,但是 Antlr 网站现在似乎已经关闭了一段时间。

我查看了以下内容:ANTLR exception handling with "$", Java并遵循该示例,但是当 Lexer 通过添加 RuntimeException() 生成代码时,我得到了无法访问的代码。

我不知道该怎么做。

当我尝试从解析器中获取语法错误数时,它显示为 0。

编辑:

我通过查看找到了一个可行的解决方案:ANTLR not throwing errors on invalid input

但是,当我尝试取回异常消息时,它是空的。我是否正确设置了所有内容?请查看示例语法:

grammar i;

options {
output=AST;
}

@header {
package com.data;
}

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

// by having these below it makes no difference
/**@parser::members {
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException("Exception : " + " " + e.getMessage());
}
}

@lexer::members {
@Override
public void reportError(RecognitionException e) {
throw new RuntimeException("Exception : " + " " + e.getMessage());
}
}*/

编辑:

请看我目前有什么:

grammar i;

options {
output=AST;
}

@header {
package com.data;
}

@rulecatch {
// ANTLR does not generate its normal rule try/catch
catch(RecognitionException e) {
throw e;
}
}

@parser::members {
@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
String hdr = getErrorHeader(e);
String msg = getErrorMessage(e, tokenNames);
throw new RuntimeException(hdr + ":" + msg);
}
}

@lexer::members {
@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
String hdr = getErrorHeader(e);
String msg = getErrorMessage(e, tokenNames);
throw new RuntimeException(hdr + ":" + msg);
}
}

operatorLogic : 'AND' | 'OR';
value : STRING;
query : (select)*;
select : 'SELECT'^ functions 'FROM table' filters?';';
operator : '=' | '!=' | '<' | '>' | '<=' | '>=';
filters : 'WHERE'^ conditions;
members : STRING operator value;
conditions : (members (operatorLogic members)*);
functions : '*';
STRING : ('a'..'z'|'A'..'Z')+;
WS : (' '|'\t'|'\f'|'\n'|'\r')+ {skip();}; // handle white space between keywords

public class Processor {

public Processor() {

}

/**
* This method builds the MQL Parser.
* @param args the args.
* @return the built IParser.
*/
private IParser buildMQLParser(String query) {
CharStream cs = new ANTLRStringStream(query);
// the input needs to be lexed
ILexer lexer = new ILexer(cs);
CommonTokenStream tokens = new CommonTokenStream();
IParser parser = new IParser(tokens);
tokens.setTokenSource(lexer);
// use the ASTTreeAdaptor so that the grammar is aware to build tree in AST format
parser.setTreeAdaptor((TreeAdaptor) new ASTTreeAdaptor().getASTTreeAdaptor());
return parser;
}

/**
* This method parses the MQL query.
* @param query the query.
*/
public void parseMQL(String query) {
IParser parser = buildMQLParser(query);
CommonTree commonTree = null;
try {
commonTree = (CommonTree) parser.query().getTree();
}
catch(Exception e) {
System.out.println("Exception :" + " " + e.getMessage());
}
}
}

public class ASTTreeAdaptor {

public ASTTreeAdaptor() {

}

/**
* This method is used to create a TreeAdaptor.
* @return a treeAdaptor.
*/
public Object getASTTreeAdaptor() {
TreeAdaptor treeAdaptor = new CommonTreeAdaptor() {
public Object create(Token payload) {
return new CommonTree(payload);
}
};
return treeAdaptor;
}
}

所以当我输入以下内容时: 从表中选择 *

没有';'我得到一个 MismatchedTokenException:

catch(Exception e) {
System.out.println("Exception : " + " " e);
}

当我尝试时:

e.getMessage();

它返回 null。

最佳答案

尝试改写 displayRecognitionError:

@parser::members { 
...

@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
String hdr = getErrorHeader(e);
String msg = getErrorMessage(e, tokenNames);
throw new RuntimeException(hdr + ":" + msg);
}
...
}
//same code in @lexer::members

如果您想跟踪错误而不是中止错误,您可以创建一个处理程序接口(interface)来跟踪它们:

@parser::members { 
...
private YourErrorTrackerInterface errorTracker;

//getter/setter for errorTracker here

@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
String hdr = getErrorHeader(e);
String msg = getErrorMessage(e, tokenNames);
if (errorTracker != null){
errorTracker.addError(e, tokenNames, hdr, msg);
}
}
...
}
//same code in @lexer::members

然后错误跟踪器可以决定是抛出异常还是继续。


上面的代码允许您跟踪“可恢复的”错误,即 ANTLR 可以跳过的错误。还有一些场景会产生不可恢复的错误,比如SELECT * FROM table(没有结尾的;)。在这种情况下,您必须在 parseMQL 或附近的某个地方捕获异常。 (您可以尝试编写自己的恢复代码,但我不建议您这样做。)

这是一个修改过的 parseMQL,它显示了两种不同类型的解析错误。请注意,我删除了对 getMessage 的调用,因为并非所有派生自 RecognitionException 的异常都会填充它。

public void parseMQL(String query) {
iParser parser = buildMQLParser(query);
CommonTree commonTree = null;
try {
commonTree = (CommonTree) parser.query().getTree();
} catch (MismatchedTokenException e){
//not production-quality code, just forming a useful message
String expected = e.expecting == -1 ? "<EOF>" : iParser.tokenNames[e.expecting];
String found = e.getUnexpectedType() == -1 ? "<EOF>" : iParser.tokenNames[e.getUnexpectedType()];

System.out.println("Fatal mismatched token exception: expected " + expected + " but was " + found);

} catch (RecognitionException e) {
System.out.println("Fatal recognition exception " + e.getClass().getName()
+ " : " + e);

} catch (Exception e) {
System.out.println("Other exception : " + e.getMessage());
}
}

输入 SELECT * FROM table 产生消息“致命不匹配的 token 异常:预期的‘;’但是是 ”。这个异常是由 ANTLR 直接产生的。

输入 SELECT FROM table; 生成消息“其他异常:第 1:7 行:‘FROM table’ 处缺少‘*’”。此异常是由上面的代码产生的。

关于java - Antlr 处理异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13624624/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com