我一直在努力从今天的解析器中删除所有s / r冲突。我设法删除所有这些但只有一个。
我的语言的语法应该像haskell一样。而不是main
,我有一个顶级表达式,即条目。
解析器如下所示。我还添加了Happy生成的Parser.info
文件的摘录,其中描述了转换/减少冲突。
据我所知,问题是一旦解析器遇到函数定义的varname
,就可以使用两个分支。它可以假设有更多varname
s因为它当前正在解析函数定义(具有一个或多个参数),或者它可以停止将其解析为变量表达式。之后可能的varname
就是另一个表达式。
我玩过%prec
规则并没有什么帮助。
我的第一个推理是,鉴于解析器想要转换为函数定义,我可以优先使用该规则。我还尝试向=
运算符添加优先级(用于函数定义),这样我就可以将它放在函数定义的优先级之下,但这也不起作用。我的猜测是我不完全理解解析器的工作原理。任何指针都非常感谢。
一个小小的注意事项,默认行为 - 我认为这是一种转变 - 也是所希望的行为。
state 25 contains 1 shift/reduce conflicts.
...
State 25
Definition -> varname . ':' ':' Type (rule 7)
Definition -> varname . FunctionParameters '=' Exp bl (rule 8)
Atom -> varname . (rule 20)
'(' reduce using rule 20
'<' reduce using rule 20
'>' reduce using rule 20
'/' reduce using rule 20
'*' reduce using rule 20
'-' reduce using rule 20
'+' reduce using rule 20
"eq?" reduce using rule 20
number reduce using rule 20
':' shift, and enter state 27
varname shift, and enter state 28
(reduce using rule 20)
%eof reduce using rule 20
FunctionParametersgoto state 26
%nonassoc PARS
%nonassoc VAR
%%
Program
: Definitions Exp { Program $1 $2 }
| Exp { Program [] $1 }
Definitions
: Definitions Definition { ($1 ++ [$2]) }
| Definition { [$1] }
Definition
: type upsym '=' Type { TypeDef $2 $4 }
| varname ':' ':' Type { FTypeDef $1 $4 }
| varname FunctionParameters '=' Exp bl { FDef $1 $2 $4 }
FunctionParameters
: FunctionParameters varname %prec PARS { $1 ++ [$2] }
| varname { [$1] }
Exp
: let varname '=' Exp "in" Exp { Let $2 $4 $6 }
| if Exp then Exp else Exp { If $2 $4 $6 }
| "Lam" varname "->" Exp { Abs $2 $4 }
| Form { $1 }
Form
: Juxt { $1 }
Juxt
: Juxt Atom { App $1 $2 }
| Atom { $1 }
Atom
: '(' Exp ')' { $2 }
| number { Value $ Number $1 }
| varname %prec VAR { Var $1 }
| Binfs { Value $ Binf $1 }
Binfs
: "eq?" { BinfEqual }
| '/' { BinfDiv }
| '*' { BinfTimes }
| '+' { BinfPlus }
| '-' { BinfMinus }
| '>' { BinfGT }
| '<' { BinfLT }