将所有 Antlr 解析错误获取为字符串列表

2022-09-03 00:53:22
  • 如何在字符串列表中获取 Antlr 的所有解析错误?

我使用蚂蚁,如下所示:

ANTLRInputStream input = new ANTLRInputStream(System.in);
grLexer lexer = new grLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
grParser parser = new grParser(tokens);
ParseTree tree = parser.formula();
System.out.println(tree.toStringTree(parser));

例如

line 1:0 token recognition error at: '('
line 1:1 token recognition error at: ')'
line 1:2 token recognition error at: '('
  • 如何确定解析的执行没有错误?如果只有一个解析错误,我会停止。

例如

if(tree.hasError()) // FOR EXAMPLE
   return;

答案 1
  • 您需要提供 ANTLRErrorListener 的实现,以收集有关所发生错误的信息。例如,IntelliJ 插件使用其 SyntaxErrorListener 来跟踪此信息。

  • 您可以在解析完成后检查 Parser.getNumberOfSyntaxErrors()以查看是否发生错误。请注意,这不会报告来自词法分析器的错误。确保正确报告所有错误的最佳方法是编写词法分析器,使其本身永远不会遇到语法错误,而是将无效令牌传递给解析器进行处理。


答案 2

Sam Harwell 描述它的方式类似,以下代码演示如何在调用解析器规则(如解析器)后获取语法错误列表:functionDefinitionC

语法检查器:

import c.grammar.CLexer;
import c.grammar.CParser;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;

import java.util.List;

import static org.antlr.v4.runtime.CharStreams.fromString;

public class CSyntaxChecker
{
    public static List<SyntaxError> getSyntaxErrors(String sourceCode)
    {
        CodePointCharStream inputStream = fromString(sourceCode);
        CLexer lexer = new CLexer(inputStream);
        CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
        CParser parser = new CParser(commonTokenStream);
        SyntaxErrorListener listener = new SyntaxErrorListener();
        parser.addErrorListener(listener);
        parser.functionDefinition();

        return listener.getSyntaxErrors();
    }
}

语法错误侦听器:

import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.misc.Utils;

import java.util.ArrayList;
import java.util.List;

public class SyntaxErrorListener extends BaseErrorListener
{
    private final List<SyntaxError> syntaxErrors = new ArrayList<>();

    SyntaxErrorListener()
    {
    }

    List<SyntaxError> getSyntaxErrors()
    {
        return syntaxErrors;
    }

    @Override
    public void syntaxError(Recognizer<?, ?> recognizer,
                            Object offendingSymbol,
                            int line, int charPositionInLine,
                            String msg, RecognitionException e)
    {
        syntaxErrors.add(new SyntaxError(recognizer, offendingSymbol, line, charPositionInLine, msg, e));
    }

    @Override
    public String toString()
    {
        return Utils.join(syntaxErrors.iterator(), "\n");
    }
}

语法错误:

import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;

public class SyntaxError
{
    private final Recognizer<?, ?> recognizer;
    private final Object offendingSymbol;
    private final int line;
    private final int charPositionInLine;
    private final String message;
    private final RecognitionException e;

    SyntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e)
    {
        this.recognizer = recognizer;
        this.offendingSymbol = offendingSymbol;
        this.line = line;
        this.charPositionInLine = charPositionInLine;
        this.message = msg;
        this.e = e;
    }

    public Recognizer<?, ?> getRecognizer()
    {
        return recognizer;
    }

    public Object getOffendingSymbol()
    {
        return offendingSymbol;
    }

    public int getLine()
    {
        return line;
    }

    public int getCharPositionInLine()
    {
        return charPositionInLine;
    }

    public String getMessage()
    {
        return message;
    }

    public RecognitionException getException()
    {
        return e;
    }
}

推荐