我准备了以下语法,该语法生成C逻辑和整数算术表达式的子集:
Expression:
LogicalOrExpression
LogicalOrExpression ? Expression : LogicalOrExpression
LogicalOrExpression:
LogicalAndExpression
LogicalOrExpression || LogicalAndExpression
LogicalAndExpression:
EqualityExpression
LogicalAndExpression && RelationalExpression
EqualityExpression:
RelationalExpression
EqualityExpression EqualityOperator RelationalExpression
EqualityOperator:
==
!=
RelationalExpression:
AdditiveExpression
RelationalExpression RelationalOperator AdditiveExpression
RelationalOperator:
<
>
<=
>=
AdditiveExpression:
MultiplicativeExpression
AdditiveExpression AdditiveOperator MultiplicativeExpression
AdditiveOperator:
+
-
MultiplicativeExpression:
UnaryExpression
MultiplicativeExpression MultiplicativeOperator UnaryExpression
MultiplicativeOperator:
*
/
%
UnaryExpression:
PrimaryExpression
UnaryOperator UnaryExpression
UnaryOperator:
+
-
!
PrimaryExpression:
BoolLiteral // TERMINAL
IntegerLiteral // TERMINAL
Identifier // TERMINAL
( Expression )
我想尝试使用shift / reduce解析,因此想知道这个语法是LR(k)的最小k(如果有的话)是什么? (更一般地说,如果可能的话,如何从任意语法中确定k?)
答案 0 :(得分:2)
示例语法(几乎)是运算符优先级语法或Floyd语法(FG)。为了使它成为一个FG,你必须宏观扩展其右侧仅由一个终端组成的非终端,因为运算符优先级语法必须是运算符语法,并且运算符语法具有以下特征 - 手边有两个连续的非终端。
所有运算符优先级语法都是LR(1)
。显示运算符语法是否具有优先级属性也是微不足道的,特别是在每个终端恰好出现在右侧的情况下都是微不足道的,就像在语法中一样。每个终端恰好在一个右侧出现的运算符语法总是一个运算符优先语法[1],因此总是LR(1)
。
FG是一大类语法,其中一些甚至是有用的(例如,Algol 60,由FG描述),很容易回答有关LR(k)
某些k
的问题。 1}},因为答案总是“是的,K == 1
”。只是为了精确,这里是属性。我们使用常规约定,其中语法G
是4元组(N,Σ,P,S),其中N
是一组非终端; Σ
是一组终端,P
是一组制作,S
是起始符号。我们为V
撰写N ⋃ Σ
。在任何语法中,我们都有:
N ⋂ Σ = ∅
S ∈ N
P ⊂ V+ × V*
“无上下文”要求限制P
,因此每个左侧都是一个非终端:
P ⊂ Σ × V*
在运算符语法中,P
被进一步限制:没有右侧是空的,没有右侧有两个连续的非终端:
P ⊂ Σ × (V+ − V*ΣΣV*)
在运算符优先级语法中,我们定义了三个优先级关系,⋖,⋗和≐。这些是根据关系Leads
和Trails
[2]定义的,其中`
T Leads V iff T is the first terminal in some string derived from V
T Trails V iff T is the last terminal in some string derived from V
然后:
t1 ⋖ t2 iff ∃v ϶ t2 Leads v ∧ N→V*t1vV* ∈ P
t1 ⋗ t2 iff ∃v ϶ t1 Trails v ∧ N→V*vt2V* ∈ P
t1 ≐ t2 iff N→V*t1t2V* ∈ P ∨ N→V*t1V't2V* ∈ P
直观地思考这些关系是这样的:通常当我们进行推导时,我们只是用RHS代替LHS,但假设我们用⋖ RHS ⋗
代替。然后我们可以通过丢弃非终端并将连续的⋖和colla的字符串折叠成单个符号来修改推导,最后在没有中间运算符的任何两个连续终端之间添加≐。从那以后,我们就读了关系。
现在,我们可以对任何运算符语法执行该计算,但没有什么能够强制上述关系是独占的。如果这三个关系是互斥的,那么运算符语法就是Floyd语法。
验证运算符语法是否具有互斥优先关系是直截了当的; Leads
和Trails
要求对First
和Last
进行传递性约束,大致为O(|G|2)
(它实际上是非终端数量和制作数量);从那里,可以通过对语法中所有产生的单个线性扫描来计算优先关系,即O(|G|)
。
答案 1 :(得分:1)
来自Donald Knuths On the Translation of Languages from Left to Right,摘要,
显示某些k 的语法是否为LR(k)的问题是不可判定的,
换句话说,
给定语法G,“∃k.GεLR(k)”是不可判定的。
因此,我们能做的最好的事情就是尝试为LR(0),LR(1),LR(2)等构建一个解析器。在某些时候你会成功,或者当 k 变大时,你可能会在某些时候放弃。
在这种特殊情况下,我碰巧知道你给出的语法是LALR(1),这意味着它必须是LR(1)。我知道这是因为我为类似语言编写了LALR解析器。由于显而易见的原因,它不能是LR(0)(语法{A - > x,A - > A + x}不是LR(0))。