Java 在Antlr4中强制执行语法错误

Java 在Antlr4中强制执行语法错误,java,antlr4,Java,Antlr4,我已经搜索了几个小时,试图找出如何在Antlr4侦听器中手动创建语法错误。可能吗 我创建了一个很好用的语法,其中一部分看起来像: variableExp returns [ BigDecimal value ] : VARIABLE_PREFIX n = VARIABLE_NAME ; 其中变量_前缀是类似“$”的字符 我使用的是一个监听器,在exitVariableExp()上,我根据解析器外部的信息设置了该值(它是用户输入的,因此我无法将其放入解析器中): 我遇到的问题是,用户可

我已经搜索了几个小时,试图找出如何在Antlr4侦听器中手动创建语法错误。可能吗

我创建了一个很好用的语法,其中一部分看起来像:

variableExp returns [ BigDecimal value ]
  : VARIABLE_PREFIX n = VARIABLE_NAME 
  ;
其中变量_前缀是类似“$”的字符

我使用的是一个监听器,在exitVariableExp()上,我根据解析器外部的信息设置了该值(它是用户输入的,因此我无法将其放入解析器中):

我遇到的问题是,用户可以键入任何不是变量的内容(例如$jfjfjfj),解析器将接受这一点。我想在此侦听器成员中创建一个语法错误,因为我有一个错误侦听器,它存储语法错误位置以向用户显示:

@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;
  }
@覆盖
public void syntaxError(识别器识别器、对象违规符号、int-line、int-charPositionInLine、String msg、RecognitionException e)抛出ParseCancelationException
{
System.out.println(“得到语法错误”);
误差线=线;
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));            
    }
}

当执行树遍历器时,解析器已经运行到完成,因此解析器的语法错误报告机制不可用

更好的是,只需依赖解析树节点,因为它将包含报告错误所需的所有信息

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
使用这种方法尽快停止解析(这有利于快速语法检查)。看看如何覆盖一些标准行为

尝试解析器在遇到语法错误时所做的操作:它抛出
RecognitionException
。您可以在侦听器中执行此操作,异常处理将负责报告错误(并尝试恢复)。如果您不喜欢恢复机制,并且希望完全停止解析,则需要做更多的工作。在这种情况下,您应该抛出与
RecognitionException
不同的异常(因为在所有解析器函数中都会捕获到该异常)。
BailErrorStrategy
使用这种方法尽快停止解析(这有利于快速语法检查)。看看如何覆盖一些标准行为

如果一个变量必须以
$
开头,你能不能使用一些你不知道的东西?严格地说,这不是一个语法错误。语法由语法定义。因此,只要代码遵循语法,就不会有语法错误。这可能是让您在搜索中感到不快的原因,因为事实上,您希望实现运行时或域错误,这取决于您正在构建的内容。我同意这对解析器来说不是语法错误,但在一般意义上对用户来说是语法错误。这是否意味着您不能从侦听器生成语法错误?@ScottHunter我不确定您在问什么。我正在分析用户输入的输入,它将有错误(错误的变量名),我想捕获它——最好是使用我已有的错误处理机制。为什么
$jfjfjj
不是变量名?字母部分在英语中不是一个单词,但许多变量名不是单词。是什么使这成为一个错误?如果一个变量必须以
$
开头,你能不能使用一些,你知道,不是的东西?严格地说,这不是一个语法错误。语法由语法定义。因此,只要代码遵循语法,就不会有语法错误。这可能是让您在搜索中感到不快的原因,因为事实上,您希望实现运行时或域错误,这取决于您正在构建的内容。我同意这对解析器来说不是语法错误,但在一般意义上对用户来说是语法错误。这是否意味着您不能从侦听器生成语法错误?@ScottHunter我不确定您在问什么。我正在分析用户输入的输入,它将有错误(错误的变量名),我想捕获它——最好是使用我已有的错误处理机制。为什么
$jfjfjj
不是变量名?字母部分在英语中不是一个单词,但许多变量名不是单词。什么使这成为一个错误?谢谢,这是有道理的。你如何阻止树行走?我尝试了一个解析取消异常,但无效。同样,解析程序已运行,所以解析取消将无法工作。只需将
ParseTreeWalker#walk
调用包装成一个
try..catch
并在您想要停止的地方抛出一个
异常。不过,最好不要停止,同时报告所有错误。有趣的是,我不是在给ParsetRewalker打电话。我确实得到了六次查找,因此对于一个错误(例如,解析“@jfjfjfj”)会出现异常。这就是为什么我想停止行走。我假设解析器正在调用它……同样有趣(令人沮丧)的是,试图解析两个字符($h),我的侦听器方法exitVariableExp()会被调用六次。为什么两个代币要叫六次?每次我都会引发一个RuntimeException。我必须开发和示例,现在它有很多、数千行。谢谢,这很有意义。你如何阻止树行走?我尝试了一个解析取消异常,但无效。再次,解析程序已运行