Invalid casting Antlr grammar / parser problems in C #

I am using Anlr 3.5 to generate the parser and lexer from the grammar below. This grammar should be used to read lines in order to convert them into a graph of objects for further evaluation. However, I am having problems trying to use the unaryExpression clause, so it generates a report on class exceptional exceptions:

Cannot cast object of type operandExpression_return to type unaryExpression_return.

One example of the input that causes this is

([p1 eq \"p1Value\"]) and [p2 eq \"p2Value\"] or [p3 > \"p3\"\"Val\"\"ue\"] 

this seems to be a bracket (unaryExpression) that explicitly throws an exception. Executing the same statement minus the parenthesis appears for proper parsing, as does the auxiliary expression in the parenthesis.

I can clearly see through the exception that the wrong type is being used. I just don’t understand why it is chosen by the parser, and what grammar correction it is necessary to avoid this error.

It should be noted that each of the two branches of the expression of the expression has several suitable alternatives with each of the branches of binaryOperator, but from my understanding this should be normal only by calling a less efficient greedy parser and not causing the errors that I see.

Grammar Used:

 grammar QueryExpressionGrammar; options { language=CSharp3; TokenLabelType=CommonToken; output=AST; ASTLabelType=CommonTree; } @lexer::namespace{namespace} @parser::namespace{namespace} @parser::members { public static string CleanQuotedString(string input) { return input == null ? null : input.Substring(1, input.Length - 2).Replace("\"\"", "\""); } } /*------------------------------------------------------------------ * PARSER RULES *------------------------------------------------------------------*/ public parse returns [IQueryExpression value] : exp=expression EOF {$value = $exp.value;} ; expression returns [IQueryExpression value] : lhs=operandExpression { $value = $lhs.value; } ( op=binaryOperator rhs=expression {$value = new BinaryOperationQueryExpression($lhs.value, $op.value, $rhs.value);} )* | lhs=unaryExpression { $value = $lhs.value; } ( op=binaryOperator rhs=expression {$value = new BinaryOperationQueryExpression($lhs.value, $op.value, $rhs.value);} )* ; binaryOperator returns [BinaryOperator value] : BinaryOperatorAnd {$value = BinaryOperator.And;} | BinaryOperatorOr {$value = BinaryOperator.Or;} ; unaryExpression returns [IQueryExpression value] : UnaryOperatorNot sub=expression {$value = new UnaryOperationQueryExpression(UnaryOperator.Not, $sub.value);} | OPEN_PAREN sub=expression CLOSE_PAREN {$value = new UnaryOperationQueryExpression(UnaryOperator.Paren, $sub.value);} ; operandExpression returns [IQueryExpression value] : OPEN_BRACKET p=PROPERTY OperandQueryExpressionOperatorEq v=QUOTED_STRING CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.Eq, CleanQuotedString($v.text));} | OPEN_BRACKET p=PROPERTY OperandQueryExpressionOperatorLt v=QUOTED_STRING CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.Lt, CleanQuotedString($v.text));} | OPEN_BRACKET p=PROPERTY OperandQueryExpressionOperatorLe v=QUOTED_STRING CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.Le, CleanQuotedString($v.text));} | OPEN_BRACKET p=PROPERTY OperandQueryExpressionOperatorGt v=QUOTED_STRING CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.Gt, CleanQuotedString($v.text));} | OPEN_BRACKET p=PROPERTY OperandQueryExpressionOperatorGe v=QUOTED_STRING CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.Ge, CleanQuotedString($v.text));} | OPEN_BRACKET p=PROPERTY OperandQueryExpressionOperatorLike v=QUOTED_STRING CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.Like, CleanQuotedString($v.text));} | OPEN_BRACKET p=PROPERTY OperandQueryExpressionOperatorIlike v=QUOTED_STRING CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.Ilike, CleanQuotedString($v.text));} | OPEN_BRACKET p=PROPERTY NonValueBasedOperandQueryExpressionOperatorIsNull CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.IsNull, null);} | OPEN_BRACKET p=PROPERTY NonValueBasedOperandQueryExpressionOperatorNotNull CLOSE_BRACKET {$value = new OperandQueryExpression($p.text, OperandQueryExpressionOperator.NotNull, null);} ; /*------------------------------------------------------------------ * LEXER RULES *------------------------------------------------------------------*/ UnaryOperatorNot : 'not' | '!' ; BinaryOperatorAnd : 'and' | '&&' | '&' ; BinaryOperatorOr : 'or' | '||' | '|' ; // OperandQueryExpressionOperator that uses a comparison value OperandQueryExpressionOperatorEq : 'eq' | '==' | '=' ; OperandQueryExpressionOperatorLt : 'lt' | '<' ; OperandQueryExpressionOperatorLe : 'le' | '<=' ; OperandQueryExpressionOperatorGt : 'gt' | '>' ; OperandQueryExpressionOperatorGe : 'ge' | '>=' ; OperandQueryExpressionOperatorLike : 'like' ; OperandQueryExpressionOperatorIlike : 'ilike' ; // OperandQueryExpressionOperator that does not use a comparison value NonValueBasedOperandQueryExpressionOperatorIsNull : 'null' | 'isnull' ; NonValueBasedOperandQueryExpressionOperatorNotNull : 'notnull' ; OPEN_BRACKET: '['; CLOSE_BRACKET: ']'; OPEN_PAREN: '('; CLOSE_PAREN: ')'; PROPERTY: LETTER (ALPHA_NUMERIC | SPECIAL)*; // property definition is in line with the definition of a property definition for c# QUOTED_STRING: QUOTE (~QUOTE | (QUOTE QUOTE))* QUOTE; // values are characters, or if they contain quotes they are escaped by double quoting and surrounding value in quotes fragment DIGIT: ('0'..'9'); fragment LETTER: (('a'..'z')|('A'..'Z')); fragment ALPHA_NUMERIC: (LETTER|DIGIT); fragment SPECIAL: ('_'|'-'); fragment QUOTE: '\u0022'; WHITESPACE: (' ' | '\t' | '\n' | '\r'){ Skip(); }; // valid whitespace characters 

Code snippet to exclude exceptions in the parser inside the private method QueryExpressionGrammarParser.expression_return expression ()

 ... switch (alt3) { case 1: DebugEnterAlt(1); // QueryExpressionGrammar.g:37:4: lhs= operandExpression (op= binaryOperator rhs= expression )* { root_0 = (CommonTree)adaptor.Nil(); DebugLocation(37, 7); PushFollow(Follow._operandExpression_in_expression111); lhs=operandExpression(); PopFollow(); adaptor.AddChild(root_0, lhs.Tree); DebugLocation(37, 26); /// vvv Exception throwing on line below vvv retval.value = (lhs!=null?((QueryExpressionGrammarParser.unaryExpression_return)lhs).value:default(IQueryExpression)); DebugLocation(37, 51); // QueryExpressionGrammar.g:37:51: (op= binaryOperator rhs= expression )* try { DebugEnterSubRule(1); ... 
+4
source share
1 answer

So, here is the solution that we found out in the comments. Change this:

 expression returns [IQueryExpression value] : lhs=operandExpression { $value = $lhs.value; } ( op=binaryOperator rhs=expression {$value = new BinaryOperationQueryExpression($lhs.value, $op.value, $rhs.value);} )* | ulhs=unaryExpression { $value = $ulhs.value; } ( op=binaryOperator rhs=expression {$value = new BinaryOperationQueryExpression($ulhs.value, $op.value, $rhs.value);} )* ; 
+3
source

All Articles