Seems like it needs a semicolon, and it has end-of-input. It is hard to say more without seeing the grammar.
The relevant part of your grammar:
(2) statement -> definition SEMICOLON
(14) definition -> fn_def
Those are the only productions in which fn_def
and definition
occur on a right-hand side.
Clearly definition
can only be reduced to statement
when the lookahead token is SEMICOLON
. Since fn_def
can only appear in a valid program in a place where it can be immediately reduced to definition
(the only production is a unit production), fn_def
must be followed by a SEMICOLON
. So your parser was correct and your sample input was ungrammatical.
fn_def
has only one production:
(16) fn_def -> DEFN ID ARROW type invariants statement
in which it is evident that the last item in fn_def
is a statement
. Some statements (definition
and expression
) must be terminated by a ;
; if the fn_def
's statement
is one of those (presumably an expression, since it doesn't seem like a single definition makes for an interesting function body) then the fn_def
will have to be written with two semicolons. I doubt whether that's what you wanted.
definition
ends with either a statement
(if it's a fn_def
) or with an expression
(if it's a var_def
). You've attempted to define statement
so that it's self-delimiting (i.e. it ends with a semicolon if it doesn't end with the }
which terminates a compound_statement
. So fn_def
already either ends with a semicolon or a closing brace, and shouldn't require another semicolon. var_def
, on the other hand, ends with an expression, and therefore does. So one solution would be to push the closing semicolon into the var_def
.
Editorial comment, unrelated to the specific question being asked:
In fact, there's no obvious reason why you need to restrict loop or conditional bodies to compound statements, other than your own aesthetics; if you allow a lambda body to be a non-compound statement, there's no obvious reason why you would restrict a for loop. The grammar can be made to work either way.