Question

stackOverFlow!

I'm using antlr4 to parse the input. I have my XXXX.g4 grammar file and antlr4 maven plugin generates me some parser code on build. I am parsing input with that code:

XXXXParser parser = new XXXXParser(new CommonTokenStream(
            new XXXXLexer(new ANTLRInputStream(currentInput))));
parser.command();

In the code above "command" is the name of the rule in my grammar. Every time I launch this code, if the currentInput string doesn't fit the grammar I get an error message in my console. I would like to be able to catch these messages and use them. The question is how to achieve that?

Was it helpful?

Solution

You can write a class that implements IAntlrErrorListener<T> and then call parser.AddErrorListener() and pass in your custom error listner. Here's an example from my own code (I actually inherited from DiagnosticErrorListener):

public class CustomErrorListener : DiagnosticErrorListener
{
    private readonly List<string> _errorMessages = new List<string>();
    public IList<string> ErrorMessages { get { return _errorMessages; } }

    private readonly List<string> _warningMessages = new List<string>();
    public IList<string> WarningMessages { get { return _warningMessages; } }

    public bool HasErrors { get { return _errorMessages.Count > 0; } }
    public bool HasWarnings { get { return _warningMessages.Count > 0; } }

    private readonly bool _captureDiagnostics;

    public CustomErrorListener(bool captureDiagnosticWarnings)
    {
        _captureDiagnostics = captureDiagnosticWarnings;
    }

    public override void SyntaxError(IRecognizer recognizer, IToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e)
    {
        _errorMessages.Add(string.Format("line {0}:{1} {2} at: {3}", line, charPositionInLine, msg, offendingSymbol.Text));
    }

    public override void ReportAmbiguity(Parser recognizer, Antlr4.Runtime.Dfa.DFA dfa, int startIndex, int stopIndex, bool exact, Sharpen.BitSet ambigAlts, Antlr4.Runtime.Atn.ATNConfigSet configs)
    {
        if (_captureDiagnostics)
        {
            _warningMessages.Add(string.Format("reportAmbiguity d={0}: ambigAlts={1}, input='{2}'", GetDecisionDescription(recognizer, dfa), GetConflictingAlts(ambigAlts, configs), ((ITokenStream)recognizer.InputStream).GetText(Interval.Of(startIndex, stopIndex))));
        }
    }

    public override void ReportAttemptingFullContext(Parser recognizer, Antlr4.Runtime.Dfa.DFA dfa, int startIndex, int stopIndex, Sharpen.BitSet conflictingAlts, Antlr4.Runtime.Atn.SimulatorState conflictState)
    {
        if (_captureDiagnostics)
        {
            _warningMessages.Add(string.Format("reportAttemptingFullContext d={0}, input='{1}'", GetDecisionDescription(recognizer, dfa), ((ITokenStream)recognizer.InputStream).GetText(Interval.Of(startIndex, stopIndex))));
        }
    }

    public override void ReportContextSensitivity(Parser recognizer, Antlr4.Runtime.Dfa.DFA dfa, int startIndex, int stopIndex, int prediction, Antlr4.Runtime.Atn.SimulatorState acceptState)
    {
        if (_captureDiagnostics)
        {
            _warningMessages.Add(string.Format("reportContextSensitivity d={0}, input='{1}'", GetDecisionDescription(recognizer, dfa), ((ITokenStream)recognizer.InputStream).GetText(Interval.Of(startIndex, stopIndex))));
        }
    }
}

Then you can write code like this:

XXXXParser parser = new XXXXParser(new CommonTokenStream(
            new XXXXLexer(new ANTLRInputStream(currentInput))));
CustomErrorListener errorListener = new CustomErrorListener(false);
parser.AddErrorListener(errorListener);
parser.command();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top