在 Antlr4 中强制出现语法错误
Forcing a syntax error in Antlr4
我搜索了几个小时,试图找出如何在 Antlr4 侦听器中手动创建语法错误。可能吗?
我创建了一个运行良好的语法,其中一部分看起来像:
variableExp returns [ BigDecimal value ]
: VARIABLE_PREFIX n = VARIABLE_NAME
;
其中 VARIABLE_PREFIX 是一个字符,如“$”。
我正在使用侦听器并在 exitVariableExp() 上,我根据解析器外部的信息设置值(并且它是用户输入的,所以我无法将其放入解析器):
@Override
public void exitVariableExp(ExpressionsParser.VariableExpContext ctx)
{
System.out.println("In exitVariableExp()");
ctx.value = lookupVariable(ctx.getText());
}
我遇到的问题是用户可以键入任何不是变量的内容(例如 $jfjhfjfj),这将被解析器接受。我想在这个侦听器成员中创建一个语法错误,因为我有一个错误侦听器,它存储语法错误位置以显示给用户:
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) throws ParseCancellationException
{
System.out.println("Got syntax error.");
errorLine = line;
errorColumn = charPositionInLine;
errorMessage = msg;
}
但我不知道该怎么做。也许这是错误的方法?
执行树遍历器时,解析器已经运行完成,因此解析器的语法错误报告机制不可用。
更好的方法是,只依赖解析树节点,因为它将包含报告错误所需的所有信息。
private static final String msg = "Syntax error: '%s' is not a valid var (at %s:%s).";
@Override
public void exitVariableExp(VariableExpContext ctx) {
String value = lookupVariable(ctx.getText());
if (value == null || value.isEmpty()) {
Token tok = ctx.VARIABLE_NAME.getSymbol();
int line = tok.getLine(); // 1..n
int col = tok.getCharPositionInLine(); // 0..n
System.out.println(String.format(msg, tok.getText(), line, col));
}
}
尝试解析器在遇到语法错误时正在做什么:它抛出 RecognitionException
。您可以在您的侦听器中执行此操作,异常处理将小心并报告错误(并尝试恢复)。如果您不喜欢恢复机制并希望完全停止解析,则需要做更多的工作。在这种情况下,您应该抛出与 RecognitionException
不同的异常(因为它在所有解析器函数中都被捕获)。 BailErrorStrategy
使用这种方法尽快停止解析(这有利于快速语法检查)。看看那里如何覆盖一些标准行为。
我搜索了几个小时,试图找出如何在 Antlr4 侦听器中手动创建语法错误。可能吗?
我创建了一个运行良好的语法,其中一部分看起来像:
variableExp returns [ BigDecimal value ]
: VARIABLE_PREFIX n = VARIABLE_NAME
;
其中 VARIABLE_PREFIX 是一个字符,如“$”。
我正在使用侦听器并在 exitVariableExp() 上,我根据解析器外部的信息设置值(并且它是用户输入的,所以我无法将其放入解析器):
@Override
public void exitVariableExp(ExpressionsParser.VariableExpContext ctx)
{
System.out.println("In exitVariableExp()");
ctx.value = lookupVariable(ctx.getText());
}
我遇到的问题是用户可以键入任何不是变量的内容(例如 $jfjhfjfj),这将被解析器接受。我想在这个侦听器成员中创建一个语法错误,因为我有一个错误侦听器,它存储语法错误位置以显示给用户:
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) throws ParseCancellationException
{
System.out.println("Got syntax error.");
errorLine = line;
errorColumn = charPositionInLine;
errorMessage = msg;
}
但我不知道该怎么做。也许这是错误的方法?
执行树遍历器时,解析器已经运行完成,因此解析器的语法错误报告机制不可用。
更好的方法是,只依赖解析树节点,因为它将包含报告错误所需的所有信息。
private static final String msg = "Syntax error: '%s' is not a valid var (at %s:%s).";
@Override
public void exitVariableExp(VariableExpContext ctx) {
String value = lookupVariable(ctx.getText());
if (value == null || value.isEmpty()) {
Token tok = ctx.VARIABLE_NAME.getSymbol();
int line = tok.getLine(); // 1..n
int col = tok.getCharPositionInLine(); // 0..n
System.out.println(String.format(msg, tok.getText(), line, col));
}
}
尝试解析器在遇到语法错误时正在做什么:它抛出 RecognitionException
。您可以在您的侦听器中执行此操作,异常处理将小心并报告错误(并尝试恢复)。如果您不喜欢恢复机制并希望完全停止解析,则需要做更多的工作。在这种情况下,您应该抛出与 RecognitionException
不同的异常(因为它在所有解析器函数中都被捕获)。 BailErrorStrategy
使用这种方法尽快停止解析(这有利于快速语法检查)。看看那里如何覆盖一些标准行为。