`ArgumentNullException` thrown on parse failure instead of helpful message
RoystonS opened this issue · 7 comments
Hi there,
I've just added some extra unit tests to my parsing code (following on from #254), and I'm seeing an ArgumentNullException
thrown from inside the parser in one particular test case.
I'm using csly 2.8.0.
I've produced a simplified version of my app (with no extra dependencies this time!) which shows a failing test:
https://github.com/RoystonS/CslyNullIssue
It's the same parser as in my real app, but instead of generating an AST I've made this one simply generate a string during parsing to make reproduction easier.
The test output for the failing test is:
Message:
System.ArgumentNullException : Value cannot be null. (Parameter 'collection')
Stack Trace:
List`1.InsertRange(Int32 index, IEnumerable`1 collection)
List`1.AddRange(IEnumerable`1 collection)
SyntaxParseResult`1.AddExpectings(IEnumerable`1 expected)
EBNFRecursiveDescentSyntaxParser`2.ParseExpressionRule(IList`1 tokens, Rule`1 rule, Int32 position, String nonTerminalName)
EBNFRecursiveDescentSyntaxParser`2.Parse(IList`1 tokens, Rule`1 rule, Int32 position, String nonTerminalName)
RecursiveDescentSyntaxParser`2.ParseNonTerminal(IList`1 tokens, String nonTerminalName, Int32 currentPosition)
EBNFRecursiveDescentSyntaxParser`2.Parse(IList`1 tokens, Rule`1 rule, Int32 position, String nonTerminalName)
RecursiveDescentSyntaxParser`2.ParseNonTerminal(IList`1 tokens, String nonTerminalName, Int32 currentPosition)
RecursiveDescentSyntaxParser`2.ParseNonTerminal(IList`1 tokens, NonTerminalClause`1 nonTermClause, Int32 currentPosition)
EBNFRecursiveDescentSyntaxParser`2.ParseExpressionRule(IList`1 tokens, Rule`1 rule, Int32 position, String nonTerminalName)
<34 more frames...>
RecursiveDescentSyntaxParser`2.ParseNonTerminal(IList`1 tokens, NonTerminalClause`1 nonTermClause, Int32 currentPosition)
EBNFRecursiveDescentSyntaxParser`2.ParseExpressionRule(IList`1 tokens, Rule`1 rule, Int32 position, String nonTerminalName)
EBNFRecursiveDescentSyntaxParser`2.Parse(IList`1 tokens, Rule`1 rule, Int32 position, String nonTerminalName)
RecursiveDescentSyntaxParser`2.ParseNonTerminal(IList`1 tokens, String nonTerminalName, Int32 currentPosition)
EBNFRecursiveDescentSyntaxParser`2.Parse(IList`1 tokens, Rule`1 rule, Int32 position, String nonTerminalName)
RecursiveDescentSyntaxParser`2.Parse(IList`1 tokens, String startingNonTerminal)
Parser`2.ParseWithContext(IList`1 tokens, Object parsingContext, String startingNonTerminal)
Parser`2.Parse(String source, String startingNonTerminal)
ExpressionParser.Parse[T](String expression) line 94
UnitTest1.BooleanParser(String expression, String expected) line 52
This particular test is a fairly heavily nested expression
1 < 2 && 1 <= 2 && 1 == 2 && 1 >= 2 && 1 > 2 && 1 != 2 && 1 <> 2
This test case is checking grouping behaviour and also doing exhaustive testing of all my operators. The expected parse result should be
(((((((1 < 2) AND (1 <= 2)) AND (1 == 2)) AND (1 >= 2)) AND (1 > 2)) AND (1 != 2)) AND (1 != 2))
but the parse is throwing ArgumentNullException
.
looking at the callstack I suspect that issue #254 fix is the root of this bug. I will look a it tomorrow. thanks for reporting
I've just done a little more debugging myself, and it looks like this particular expression is actually invalid. (This parser grammar is missing the actual parsing logic for the <>
operator, so should be failing.)
I've just wound back to csly 2.7.0.5 and I get different behaviour. I get a nice clear error message instead:
System.Exception : unexpected "COMPARISON [>] @line 1, column 80" (COMPARISON). Expecting MINUS, LVAR, SIMVAR, LPAREN, OFF, ON, HEX_NUMBER, DECIMAL_NUMBER, .
So the problem is a pretty minor one: the error message has simply gotten lost in the 2.8.0 update, not that something has fundamentally gone wrong with the parser.
hello @RoystonS ,
I 've found a fix. You can test it on branch bugfix/#259
As soon as you're ok , i will build a new release
Yep, looks good!
I am not totally satisified with the error message that states :
unexpected "COMPARISON [<] @line 1, column 67" (COMPARISON). Expecting LOGICAL_OR, .
the "<" token is legit at position 67. I was hoping something like
unexpected "COMPARISON [>] @line 1, column 68" (COMPARISON). Expecting ...... .
I guess the expected tokens should be operands :
- LVAR
- SIMVAR
- LPAREN
- OFF
- ON
- HEX_NUMBER
- DECIMAL_NUMBER
- maybe i'm missing some
I've pushed one more fix that help deliver better error message :
unexpected "COMPARISON [>] @line 1, column 72" (COMPARISON). Expecting MINUS, OFF, ON, HEX_NUMBER, DECIMAL_NUMBER, LVAR, SIMVAR, LPAREN, .
You can test it on the same branch as previously
I 've release nuget 2.8.0.1