ifequal构造语法实现

时间:2014-01-14 13:50:59

标签: grammar shift-reduce-conflict

我必须创建识别这个的语法:

ifequal(exp1, exp2) 
    statement1
smaller
    statement2
larger
    statement3

如果两个表达式相等,则执行statement1;如果第一个小于第三个,则执行第二个(如果它更大)。我尝试制作类似于this解决方案但没有运气的东西。我不能使用优先级,因此必须正确更改语法。我正在使用cup工具生成解析器。

编辑:越来越小的部分是可选的。

1 个答案:

答案 0 :(得分:1)

如果(如果没有别的话)问题,这是古老的悬挂。如果你写一些像

这样的代码
if (a == b) then
    if (b == c) then
        do_something;
    else
        do_something_else;

解析器在确定“if”属于哪个“if”时会遇到问题。 一种解决方案是添加分隔符,如“endif”。例如:

if (a == b) then
    if (b == c) then
        do_something;
    endif;
    else
        do_something_else;
endif;

不再被缩进混淆了(我故意做错了),现在很清楚该做什么。

这就是为什么像下面概述的那样的语法不起作用(它会产生很多冲突):

stmtlist: stmt
    | stmtlist stmt

stmt: ifequal
    | something_else

ifequal: IFEQUAL '(' expr ',' expr ')' stmtlist opt_lt_gt

opt_lt_gt:
    | SMALLER stmtlist
    | LARGER stmtlist
    | SMALLER stmtlist LARGER stmtlist

但是一旦语句列表以某种方式与IFEQUAL语句分开,例如通过使用大括号,问题就消失了。

stmtlist: '{' stmtseq '}'

stmtseq: stmt
     |   stmtseq stmt

另一种可能性是禁止stmtlist中的不完整语句。这或多或少会使你的语法加倍。它可能看起来像

fullifequal: IFEQUAL '(' expr ',' expr ')' fstmtlist SMALLER fstmtlist LARGER fstmtlist

fstmtlist: fullstmt
    |      fstmtlist fullstmt

fullstmt: fullifequal
    |     some_other

ifequal:  IFEQUAL '(' expr ',' expr ')' fstmtlist opt_lt_gt

opt_lt_gt:
     |     SMALLER fstmtlist
     |     LARGER  fstmtlist
     |     SMALLER fstmtlist LARGER fstmtlist

我个人更喜欢大括号解决方案,因为它易于阅读,不会限制“ifequal”语句中的语句,并且解析器代码会更短。但我想你需要另一种解决方案。