这种语法很愚蠢,因为它将词法分析和解析结合为一个。但是,好吧,这是一个学术例子。
自下而上和自上而下的事情是有特殊的极端情况,很难用你的正常 1 前瞻来实现。我可能认为您应该检查它是否有任何问题并更改语法。
为了理解你的语法,我写了一个正确的 EBNF
expr:
expr op expr |
'(' expr ')' |
number;
op:
'+' |
'-' |
'*' |
'/';
number:
'0' |
digit digits;
digits:
'0' |
digit |
digits digits;
digit:
'1' |
'2' |
'3' |
'4' |
'5' |
'6' |
'7' |
'8' |
'9';
我特别不喜欢这个规则digits: digits digits
。目前尚不清楚第一个数字从哪里开始,第二个数字在哪里结束。我会将规则执行为
digits:
'0' |
digit |
digits digit;
另一个问题是number: '0' | digit digits;
This 与digits: '0'
and冲突digits: digit;
。事实上,这是重复的。我会将规则更改为(删除数字):
number:
'0' |
digit |
digit zero_digits;
zero_digits:
zero_digit |
zero_digits zero_digit;
zero_digit:
'0' |
digit;
这使得语法 LR1(左递归,向前看)和上下文无关。这是您通常会提供给解析器生成器(例如野牛)的内容。由于 bison 是自下而上的,这对于自下而上的解析器来说是一个有效的输入。
对于自上而下的方法,至少对于递归体面而言,左递归有点问题。如果愿意,您可以使用回滚,但对于这些,您需要 RR1(右递归前瞻)语法。为此交换递归:
zero_digits:
zero_digit |
zero_digit zero_digits;
我不确定这是否能回答你的问题。我认为这个问题表述不当且具有误导性;我以编写解析器为生...