这是古代悬而未决(如果没有别的)问题。如果您编写一些代码,如
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”语句和解析器代码中的语句会更短。但我想你会需要另一种解决方案。