I am getting started with tatsu and I am trying to implement a grammar for the miniML language. Once my grammar successfully parsed, I tried to parse some little expressions to check that it was working ; however I discovered Tatsu was unable to recognize some of the expected patterns.
Here is the code :
`
grammar="""
@@grammar::CALC
start
=
expression $
;
expression
=
|integer
|addition
|soustraction
|multiplication
|division
|Fst
|Snd
|pair
|varname
|assign
|function
|application
|parentheses
;
integer
=
/\d /
;
addition
=
left:' ' right:pair
;
soustraction
=
'-' pair
;
multiplication
=
'*' pair
;
division
=
'/' pair
;
Fst
=
'Fst' pair
;
Snd
=
'Snd' pair
;
pair
=
'(' expression ',' expression ')'
;
varname
=
/[a-z] /
;
assign
=
varname '=' expression ';' expression
;
function
=
'Lambda' varname ':' expression
;
application
=
' '<{expression}
;
parentheses
=
'(' expression ')'
;
"""
`
then parsed :
parser = tatsu.compile(grammar)
All of those expression are successfully recognized, except the "assign" and the "application" ones. If i try something like this :
parser.parse("x=3;x 1")
I get that error message :
FailedExpectingEndOfText: (1:2) Expecting end of text :
x=3;x 1
^
start
and same goes for an expression of the type "expression expression". What could be the syntax error I made here ? I have no clue and I can't find any in the documentation.
Thanks in advance !
CodePudding user response:
- It seems the failure of
assign
comes from a conflict with thevarname
rule; to solve it, simply place|assign
BEFORE|variable
in yourexpression
rule.
A now obsolete workaround, that I'll leave anyway:
# I added a negative lookahead for '=' so it will not conflict with the assign rule
varname = /[a-z] /!'=' ;
assign = /[a-z] / '=' expression ';' expression ;
Example:
parser.parse("x=1; (x,1)")
# ['x', '=', '1', ';', AST({'left': ' ', 'right': ['(', 'x', ',', '1', ')']})]
- About 'application' : replacing
' '
with/ /
at the start of the rule, and placing|application
at the start of theexpression
rule solves the problem:
parser.parse("1 2 (x=1;3) *(4,5)")
Out[207]:
(' ',
'1',
(' ',
'2',
(' ',
['(', ['x', '=', '1', ';', '3'], ')'],
['*', ['(', '4', ',', '5', ')']])))