2014-01-14 62 views
0

我要创建语法识别这样的:如果两个表达式等于执行ifequal构建语法实施

ifequal(exp1, exp2) 
    statement1 
smaller 
    statement2 
larger 
    statement3 

语句1,第二如果第一较小第三如果是较大的。我试图做出类似this解决方案,但没有运气。我不能使用优先顺序,所以必须正确地更改语法。我正在使用杯子工具来生成解析器。

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

回答

1

这是古代悬而未决(如果没有别的)问题。如果您编写一些代码,如

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

解析器在决定“其他”属于哪个“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”语句和解析器代码中的语句会更短。但我想你会需要另一种解决方案。