改写语法去除移位减lessif-then-else中的冲突
如何删除给定语法的野牛移位 – 减less冲突?
selection-stmt -> if ( expression ) statement | if ( expression ) statement else statement
提供修改过的语法的解决scheme将受到高度赞赏。
有一个更简单的解决scheme。 如果你知道LRparsing器是如何工作的,那么你知道冲突发生在这里:
if ( expression ) statement * else statement
星号标记光标的当前位置。 parsing器必须回答的问题是“我应该移位还是应该减less”。 通常情况下,你想绑定else
的最接近的,这意味着你现在想要移动else
标记。 现在减less意味着你想要else
等待被绑定到一个“老” if
。
现在,您要“告诉”您的parsing器生成器:“如果标记"else"
和规则”stm – > if(exp)stm“之间存在移位/减less冲突,则标记必须取胜”。 为此,请为您的规则的优先级(例如"then"
)指定一个名称,并指定"then"
优先级低于"else"
。 就像是:
// Precedences go increasing, so "then" < "else". %nonassoc "then" %nonassoc "else" %% stm: "if" "(" exp ")" stm %prec "then" | "if" "(" exp ")" stm "else" stm
使用Bison语法。
其实,我最喜欢的答案是甚至给予"then"
和"else"
相同的优先顺序。 当优先级相等时,为了打破想要移位的标记与想要减less的规则之间的联系,Bison / Yacc将关注联合性。 在这里,你想要宣扬右倾关联(更确切地说,你想促进“移位”),所以:
%right "then" "else" // Same precedence, but "shift" wins.
就足够了。
你需要认识到if-else情况下的中间statement
不能以(如果没有别的方式)悬空(或者以其他方式结束)。最简单的方法是将stmt
规则分成两部分:
stmt -> stmt-ending-with-dangling-if | stmt-not-ending-with-dangling-if stmt-not-ending-with-dangling-if -> if ( expression ) stmt-not-ending-with-dangling-if else stmt-not-ending-with-dangling-if | ...other statements not ending with dangling if... stmt-ending-with-dangling-if -> if ( expression ) stmt | if ( expression ) stmt-not-ending-with-dangling-if else stmt-ending-with-dangling-if | ...other statements ending with dangling if...
任何其他的stmt -> whatever
不以stmt
stmt-not-ending-with-if
规则都会在stmt-not-ending-with-if
规则中出现,而以stmt
结尾的任何stmt
规则都会被分成两个版本; not-ending-with-if
规则中not-ending-with-if
规则和dangling-if
在dangling-if
规则中的dangling-if
dangling-if
版本中的not-ending-with-if
。
编辑
与其他作品更完整的语法:
stmt : stmt-ending-with-dangling-if | stmt-not-ending-with-dangling-if stmt-not-ending-with-dangling-if : IF '(' expr ')' stmt-not-ending-with-dangling-if ELSE stmt-not-ending-with-dangling-if | WHILE '(' expr ')' stmt-not-ending-with-dangling-if | DO stmt WHILE '(' expr ')' ';' | expr ';' | '{' stmt-list '}' stmt-ending-with-dangling-if: IF '(' expr ')' stmt | IF '(' expr ')' stmt-not-ending-with-dangling-if ELSE stmt-ending-with-dangling-if | WHILE '(' expr ')' stmt-ending-with-dangling-if
像WHILE (expr) stmt
这样的规则可以分成两部分(以stmt
结尾),而像expr;
这样的规则expr;
不要。
如果比正常的语句更高一些,比如:
statements: statements lineEnd statement | statements lineEnd IfStat | statements lineEnd IfElseStat | IfStat | IfElseStat ; IfStat: if ( statement ) ; IfElse: IfStat else statement ;