Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 2.7 & ANTLR4 : Make ANTLR throw exceptions on invalid input

I want to catch errors like

line 1:1 extraneous input '\r\n' expecting {':', '/',}

line 1:1 mismatched input 'Vaasje' expecting 'Tafel'

I tried wrapping my functions in try-catch but, as expected, these errors are just print statement and not exceptions. I've seen some examples of switching on errors in the .g4 file, but all the examples are for Java, and I can't seem to get it working.

Is it possible for ANTLR4 in Python to throw exceptions which I can catch?

like image 900
Emiel Steerneman Avatar asked Aug 26 '15 11:08

Emiel Steerneman


Video Answer


1 Answers

I have looked through the python classes and noticed that they dont have the methods that the java one has for adding and removing a error listener, this maybe a bug in ANTLR, however python being python you are allowed to modify the members without requiring a setter as such like in the following example:

I run the example by performing a : antlr4 -Dlanguage=Python2 AlmostEmpty.g4 and then by typing in main.py


AlmostEmpty.g4

grammar AlmostEmpty;

animals: (CAT | DOG | SHEEP ) EOF;

WS: [ \n\r]+ -> skip;
CAT: [cC] [aA] [tT];
DOG: [dD] [oO] [gG];
SHEEP: [sS] [hH] [eE] [pP];

main.py

from antlr4 import *
import sys
from AlmostEmptyLexer import AlmostEmptyLexer
from AlmostEmptyParser import AlmostEmptyParser
from antlr4.error.ErrorListener import ErrorListener

class MyErrorListener( ErrorListener ):

    def __init__(self):
        super(MyErrorListener, self).__init__()

    def syntaxError(self, recognizer, offendingSymbol, line, column, msg, e):
        raise Exception("Oh no!!")

    def reportAmbiguity(self, recognizer, dfa, startIndex, stopIndex, exact, ambigAlts, configs):
        raise Exception("Oh no!!")

    def reportAttemptingFullContext(self, recognizer, dfa, startIndex, stopIndex, conflictingAlts, configs):
        raise Exception("Oh no!!")

    def reportContextSensitivity(self, recognizer, dfa, startIndex, stopIndex, prediction, configs):
        raise Exception("Oh no!!")

if __name__ == "__main__":
    inputStream = StdinStream( )
    lexer = AlmostEmptyLexer(inputStream)
    # Add your error listener to the lexer if required
    #lexer.removeErrorListeners()
    #lexer._listeners = [ MyErrorListener() ]
    stream = CommonTokenStream(lexer)
    parser = AlmostEmptyParser(stream)
    # As mentioned in the comments by @Tim Stewart instead of doing this:
    # parser._listeners = [ MyErrorListener() ]
    # you can do this:
    parser.addErrorListener( MyErrorListener() )
    tree = parser.animals()
like image 185
Har Avatar answered Sep 26 '22 06:09

Har