I have a simple ANLTR grammar and accompanying Visitor. Everything works great, unless the input is invalid. If the input is invalid, the errors get swallowed and my calculator comes out with the wrong output.
I've tried implementing an error listener, over riding the Recover
method of the lexer, and.. well... half a dozen other things today. Can someone show me how to simply throw an error instead of swallowing bad "tokens"? (I use quotes because they're not tokens at all. The characters are undefined in my grammar.)
Valid Input:
1 + 2 * 3 - 4
Invalid Input:
1 + 2 + 3(4)
I want to throw an ArgumentException
if the parser/lexer comes across parenthesis (or any other undefined character). Currently, the invalid characters seem to just disappear into the ether and the parser just plods along like nothing is wrong.
If I run it in the console with the grun
command, I get the following output, so it recognizes the invalid tokens on some level.
line 1:9 token recognition error at: '('
line 1:11 token recognition error at: ')'
and this resulting parse tree.
BasicMath.g4
grammar BasicMath;
/*
* Parser Rules
*/
compileUnit : expression+ EOF;
expression :
expression MULTIPLY expression #Multiplication
| expression DIVIDE expression #Division
| expression ADD expression #Addition
| expression SUBTRACT expression #Subtraction
| NUMBER #Number
;
/*
* Lexer Rules
*/
NUMBER : INT; //Leave room to extend what kind of math we can do.
INT : ('0'..'9')+;
MULTIPLY : '*';
DIVIDE : '/';
SUBTRACT : '-';
ADD : '+';
WS : [ \t\r\n] -> channel(HIDDEN);
Calculator:
public static class Calculator
{
public static int Evaluate(string expression)
{
var lexer = new BasicMathLexer(new AntlrInputStream(expression));
var tokens = new CommonTokenStream(lexer);
var parser = new BasicMathParser(tokens);
var tree = parser.compileUnit();
var visitor = new IntegerMathVisitor();
return visitor.Visit(tree);
}
}
User-Defined Exception for Invalid Input in Java Let's create an exception if the user enters an ID. If it is not present in the database, the invalid id exception is thrown. The code creates an exception thrown when the input ID is invalid, which means not present in the database.
Any code can throw an exception: your code, code from a package written by someone else such as the packages that come with the Java platform, or the Java runtime environment. Regardless of what throws the exception, it's always thrown with the throw statement.
An exception is thrown for one of three reasons: An abnormal execution condition was synchronously detected by the Java virtual machine. Such conditions arise because: evaluation of an expression violates the normal semantics of the language, such as an integer divide by zero, as summarized in §15.6.
For example, we can check an input parameter to our method and throw an IllegalArgumentException if it is invalid: public void calculate(int n) { if (n > MAX_VALUE) { throw new IllegalArgumentException("Value too big (" + n + ")"); } ... }
Actually each error message is caused by an exception. This exception is caught and the parser tries to recover. The parse tree is the result of the recovering.
Since the error occurs in the lexer (the lexer just does not know the characters (
or )
), the error handling must be attached to the lexer. In Java this would look like:
lexer.addErrorListener(new BaseErrorListener() {
@Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
throw new RuntimeException(e);
}
});
The C# Syntax should not be far from that. Yet I recommend not to throw an exception. Better collect the errors into a list and report them after the lexer finished and do not start parsing if the list of errors is not empty.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With