我正在尝试解析不带分隔符的表达式序列,以便能够解析 ML/F# 样式的函数调用:
myfunc expr1 expr2 expr3
但是,表达式序列给了我一个移位/减少冲突的列表。
我的猜测是冲突是由我的语法的递归性质引起的,但我不知道如何解决这些冲突。
我的(简化的)优先规则和语法如下所示:
/* Lowest precedence */
%left PLUS
%left TIMES
%left LPAR
/* Highest precedence */
Expr:
| CSTINT { CstI $1 }
| LPAR Expr RPAR { $2 }
| Expr TIMES Expr { Prim("*", $1, $3) }
| Expr PLUS Expr { Prim("+", $1, $3) }
| NAME ExprList { Call(Var $1, $2) }
ExprList:
| { [] }
| Expr ExprList { $1::$2 }
当我将它传递给 fsyacc 时,我会得到一个 shift/reduce 和 reduce/reduce 冲突列表。一个示例移位/减少冲突是
state 11: shift/reduce error on PLUS
状态 11 的 fsycc 的输出是:
state 11:
items:
Expr -> Expr . 'TIMES' Expr
Expr -> Expr . 'PLUS' Expr
ExprList -> Expr . ExprList
actions:
action 'EOF' (noprec): reduce ExprList -->
action 'LPAR' (explicit left 10000): shift 6
action 'RPAR' (noprec): reduce ExprList -->
action 'COMMA' (noprec): reduce ExprList -->
action 'PLUS' (explicit left 9998): shift 13
action 'TIMES' (explicit left 9999): shift 12
action 'NAME' (noprec): shift 14
action 'CSTINT' (noprec): shift 5
action 'error' (noprec): reduce ExprList -->
action '#' (noprec): reduce ExprList -->
action '$$' (noprec): reduce ExprList -->
immediate action: <none>
gotos:
goto Expr: 11
goto ExprList: 16
自从我学习编译器理论课程以来已经有一段时间了,所以虽然我知道什么是移位/归约和归约/归约冲突,但我不习惯思考它们。特别是,我看不到减少如何PLUS
导致有效的解析。总而言之,对以下一个或多个问题的任何见解都将受到高度赞赏:
- 为什么我的语法看起来模棱两可?
- 我可以使用优先级和/或关联性规则来修复它吗,或者,如果不是,
- 我是否需要重写语法,如果需要,大致上,我该怎么做?
- yacc 是适合这种构造的工具吗?