我必须创建识别这一点的语法:
ifequal(exp1, exp2)
statement1
smaller
statement2
larger
statement3
如果两个表达式相等,则执行 statement1,如果第一个较小,则执行第二个,如果较大,则执行第三个。我试图做出与此解决方案类似的东西,但没有运气。我不能使用优先级,因此必须正确更改语法。我正在使用杯子工具生成解析器。
编辑:更小和更大的部分是可选的。
我必须创建识别这一点的语法:
ifequal(exp1, exp2)
statement1
smaller
statement2
larger
statement3
如果两个表达式相等,则执行 statement1,如果第一个较小,则执行第二个,如果较大,则执行第三个。我试图做出与此解决方案类似的东西,但没有运气。我不能使用优先级,因此必须正确更改语法。我正在使用杯子工具生成解析器。
编辑:更小和更大的部分是可选的。
这是古老的悬空 if(如果没有 else)问题。如果您编写一些代码,例如
if (a == b) then
if (b == c) then
do_something;
else
do_something_else;
解析器在决定“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”语句中,并且解析器代码会更短。但我想你需要其他解决方案。