Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all Antlr parsing errors as list of string

  • How can I get all parsing errors of Antlr in a list of strings?

I use antlr as follows:

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));

For example

line 1:0 token recognition error at: '('
line 1:1 token recognition error at: ')'
line 1:2 token recognition error at: '('
  • How can I find out that parsing is executed without an error? I would stop if there is only one parsing error.

For example

if(tree.hasError()) // FOR EXAMPLE
   return;
like image 607
HamedFathi Avatar asked Feb 09 '14 16:02

HamedFathi


2 Answers

  • You need to provide an implementation of ANTLRErrorListener to gather information about the errors that occur. For example, the IntelliJ plugin uses its SyntaxErrorListener to track this information.

  • You can check Parser.getNumberOfSyntaxErrors() after the parse is complete to see if an error occurred. Note that this doesn't report errors from the lexer. The best way to make sure all errors are reported properly is to write your lexer in such a way that it can never encounter a syntax error itself, but instead passes invalid tokens on to the parser for handling.

like image 157
Sam Harwell Avatar answered Nov 14 '22 00:11

Sam Harwell


Similar to how Sam Harwell described it, the following code demonstrates getting a list of the syntax errors after invoking a parser rule such as functionDefinition for a C parser:

Syntax checker:

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();
    }
}

Syntax error listener:

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");
    }
}

Syntax error:

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;
    }
}
like image 38
BullyWiiPlaza Avatar answered Nov 14 '22 00:11

BullyWiiPlaza