解析器不知道要做什么时的默认行为是将消息打印到终端,例如:
第1:23行在“}”处缺少DECIMAL
这是一个很好的信息,但是在错误的位置。我宁愿将此作为例外。
我尝试使用BailErrorStrategy
,但是会抛出一个ParseCancellationException
没有消息的消息(由引起InputMismatchException
,也没有消息)。
有什么办法可以让我通过异常报告错误,同时又保留消息中的有用信息?
这就是我真正想要的—我通常在规则中使用动作来构建对象:
dataspec returns [DataExtractor extractor]
@init {
DataExtractorBuilder builder = new DataExtractorBuilder(layout);
}
@after {
$extractor = builder.create();
}
: first=expr { builder.addAll($first.values); } (COMMA next=expr { builder.addAll($next.values); })* EOF
;
expr returns [List<ValueExtractor> values]
: a=atom { $values = Arrays.asList($a.val); }
| fields=fieldrange { $values = values($fields.fields); }
| '%' { $values = null; }
| ASTERISK { $values = values(layout); }
;
然后,当我调用解析器时,我将执行以下操作:
public static DataExtractor create(String dataspec) {
CharStream stream = new ANTLRInputStream(dataspec);
DataSpecificationLexer lexer = new DataSpecificationLexer(stream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DataSpecificationParser parser = new DataSpecificationParser(tokens);
return parser.dataspec().extractor;
}
我真正想要的是
dataspec()
当无法解析输入时调用引发异常(理想情况下为已检查的异常)的调用然后,我将让该异常在调用堆栈中冒泡,使其到达最适合向用户呈现有用消息的位置,就像我处理断开的网络连接,读取损坏的文件等的方法一样。
我确实看到ANTLR4中的动作现在被认为是“高级”的,所以也许我正在以一种奇怪的方式来处理事情,但是自从这种方式以来,我没有研究过“非高级”方式是什么。一直很好地满足我们的需求。
由于我对现有的两个答案有些挣扎,所以我想分享一下最终得到的解决方案。
首先,我像SamHarwell建议的那样创建了自己的ErrorListener版本:
public class ThrowingErrorListener extends BaseErrorListener {
public static final ThrowingErrorListener INSTANCE = new ThrowingErrorListener();
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
throws ParseCancellationException {
throw new ParseCancellationException("line " + line + ":" + charPositionInLine + " " + msg);
}
}
请注意使用aParseCancellationException
而不是a,RecognitionException
因为DefaultErrorStrategy会捕获后者,并且永远不会到达您自己的代码。
建议不要像BradMace一样创建一个全新的ErrorStrategy,因为DefaultErrorStrategy默认情况下会产生非常好的错误消息。
然后,我在解析函数中使用自定义的ErrorListener:
public static String parse(String text) throws ParseCancellationException {
MyLexer lexer = new MyLexer(new ANTLRInputStream(text));
lexer.removeErrorListeners();
lexer.addErrorListener(ThrowingErrorListener.INSTANCE);
CommonTokenStream tokens = new CommonTokenStream(lexer);
MyParser parser = new MyParser(tokens);
parser.removeErrorListeners();
parser.addErrorListener(ThrowingErrorListener.INSTANCE);
ParserRuleContext tree = parser.expr();
MyParseRules extractor = new MyParseRules();
return extractor.visit(tree);
}
这将为您提供与默认情况下打印到控制台相同的错误消息,只是形式为适当的异常。
ANTLR4书引用了一个多模式示例 https://github.com/stfairy/learn-antlr4/blob/master/tpantlr2-code/lexmagic/ModeTagsLexer.g4 https://github.com/stfairy/learn-antlr4/blob/master/tpantlr2-code/lexmagic/ModeTagsParser.
问题内容: 我有一系列要解决的承诺 我继续继续诺言链。看起来像这样 我想添加一个catch语句来处理单个promise,以防万一出错,但是当我尝试时,返回它发现的第一个错误(忽略其余的),然后我无法从其余的promise中获取数据数组(没有错误)。 我尝试做类似.. 但这并不能解决。 谢谢! - 编辑: 下面的答案完全正确,但代码由于其他原因而中断。如果有人感兴趣,这就是我最终得到的解决方案… 节
问题内容: 有没有一种方法来处理错误,比如,你可以在使用块,等等? 我已经在网上搜索过,发现的唯一选择是global变量,但是它没有按我预期的那样工作,例如,以下代码: 确实会以某种方式回滚,因为我在table1上更改的名称保留了我在此处进行测试时的旧值,但是它不会打印消息,也不会执行我在导致错误的指令之后放置的任何指令 有人可以帮我吗?您知道Sybase错误处理是如何工作的吗? 问题答案: 第一
问题内容: jQuery的getScript函数似乎不支持错误回调函数。我不能在这里使用全局ajax错误处理代码,局部错误功能将是理想的选择。 回调获取data / textStatus的文档似乎不正确-回调均不获取。 关于如何检测到对getScript的调用失败的任何建议(例如,服务器不可用)? 编辑:仅查看源代码,似乎回调仅在成功时才调用,数据始终设置为null且未定义textStatus(因
Ansible 通常默认会确保检测模块和命令的返回码并且会快速失败 – 专注于一个错误除非你另作打算. 有时一条命令会返回 0 但那不是报错.有时命令不会总是报告它 ‘改变’ 了远程系统.本章节描述了 如何将 Ansible 处理输出结果和错误处理的默认行为改变成你想要的. 忽略错误的命令 New in version 0.6. 通常情况下, 当出现失败时 Ansible 会停止在宿主机上执行.有
问题内容: 我正在使用Restify和Mongoose创建一个API ,而这两个都是我的新手。我似乎无法找出正确的方法来处理Mongoose / Node中的错误。 到目前为止,我正在尝试执行以下操作: 我正在尝试为此调用GET(针对不存在的用户)。而不是发送回简单的错误消息,而是导致整个节点应用程序失败。我对return next(err)的用户以及应该怎么做感到困惑。 任何帮助是极大的赞赏。