我正在尝试为pascal找到LR(1)或LR(0)语法。这是我的语法的一部分,它不是LR(0),因为它有转移/减少冲突。
EXPR --> AEXPR | AEXPR realop AEXPR
AEXPR --> TERM | SIGN TERM | AEXPR addop TERM
TERM --> TERM mulop FACTOR | FACTOR
FACTOR --> id | num | ( EXPR )
SIGN --> + | -
(大写单词是变量和小写单词,+, - 是终端)
如您所见,EXPR --> AEXPR | AEXPR realop AEXPR
导致LR(0)解析的转换/减少冲突。我尝试添加一个新变量,以及其他一些方法来为此找到一个等效的LR(0)语法,但我没有成功。
我有两个问题。
首先:这个语法是LR(1)语法吗?
第二:是否有可能找到这个语法的LR(0)等价物? LR(1)相当于什么?
答案 0 :(得分:2)
是的,你的语法是LR(1)语法。 [见下面的注释]
这不仅仅是导致LR(0)冲突的第一个生产。在LR(0)语法中,您必须能够在不咨询先行符号的情况下预测是否移位或减少(以及减少哪些生产)。这是一项限制性很强的要求。
尽管如此,有一种语法可以识别同一种语言。它不是一个等价语法,因为它不会产生相同的解析树(或任何有用的解析树),所以它取决于你认为等价的东西。
EXPR → TERM | EXPR OP TERM
TERM → num | id | '(' EXPR ')' | addop TERM
OP → addop | mulop | realop
以上工作忽略了运算符优先级;它将表达式简单地视为常规语言TERM (op TERM)*
。 (我将+ | -
更改为addop
,因为我无法看到您的扫描仪如何工作,但这并不重要。)
通常用于使LR(1)表达式语法适合LL(1)解析的转换,但由于允许LL(1)检查先行字符,因此能够以正常方式处理运算符优先级。 LL(1)"等价物"语法不会生成具有正确运算符关联性的解析树 - 所有运算符都变为右关联 - 但可以通过简单的树旋转来恢复正确的解析树。
在LR(0)语法的情况下,运算符优先级已经丢失,树转换几乎等同于重新分析输入,使用诸如分流码算法之类的东西来创建真正的解析树。
我不相信所呈现的语法是正确的语法,因为它使得一元加号和减号绑定比乘法更紧密,结果-3*4
被解析为-(3*4)
。碰巧的是,大部分时间都没有语义差异,但对我来说仍然感觉不对。我会把语法写成:
EXPR → AEXPR | AEXPR realop AEXPR
AEXPR → TERM | AEXPR addop TERM
TERM → FACTOR | TERM mulop FACTOR
FACTOR → num | id | '(' EXPR ')' | addop FACTOR
这使得一元运算符更紧密地绑定。 (如上所述,我假设addop
正好是+
或-
。)