a ⋖ b(a 优先级低于 b)、a ≐ b(相等)、a ⋗ b(a 高于 b)。注意 a⋖b 不等于 b⋖a。FIRSTVT(P) = { a | P ⇒⁺ a… 或 P ⇒⁺ Qa… } —— P 推出的串里"第一个终结符"(可越过开头一个非终结符)
规则:① P→a… 或 P→Qa… ⟹ a∈FIRSTVT(P)
② P→Q… ⟹ FIRSTVT(Q) ⊆ FIRSTVT(P)
LASTVT(P) = { a | P ⇒⁺ …a 或 P ⇒⁺ …aQ } —— 对称地取"最后一个终结符"
规则:① P→…a 或 P→…aQ ⟹ a∈LASTVT(P)
② P→…Q ⟹ LASTVT(Q) ⊆ LASTVT(P)
① 右部出现 …ab… 或 …aQb… ⟹ a ≐ b。
② 右部出现 …aQ… ⟹ 对每个 b∈FIRSTVT(Q):a ⋖ b。
③ 右部出现 …Qb… ⟹ 对每个 a∈LASTVT(Q):a ⋗ b。
FIRSTVT(F) = { ( , i }
FIRSTVT(T) = { * , ( , i }
FIRSTVT(E) = { + , * , ( , i }
LASTVT:
LASTVT(F) = { ) , i }
LASTVT(T) = { * , ) , i }
LASTVT(E) = { + , * , ) , i }
由三条规则推关系(举几条):
E→E+T:+ 后是 T ⟹ + ⋖ FIRSTVT(T)={*,(,i} ;T 前… E 后是 + ⟹ LASTVT(E) ⋗ +
T→T*F:* 后是 F ⟹ * ⋖ FIRSTVT(F)={(,i} ;F 前… T 后是 * ⟹ LASTVT(T) ⋗ *
F→(E):( 与 ) 夹 E ⟹ ( ≐ ) ;( ⋖ FIRSTVT(E) ;LASTVT(E) ⋗ )
句子括号 #:# ⋖ FIRSTVT(E) ;LASTVT(E) ⋗ #
优先关系表(行=栈顶终结符,列=当前输入终结符):
| + | * | ( | ) | i | # | |
|---|---|---|---|---|---|---|
| + | ⋗ | ⋖ | ⋖ | ⋗ | ⋖ | ⋗ |
| * | ⋗ | ⋗ | ⋖ | ⋗ | ⋖ | ⋗ |
| ( | ⋖ | ⋖ | ⋖ | ≐ | ⋖ | |
| ) | ⋗ | ⋗ | ⋗ | ⋗ | ||
| i | ⋗ | ⋗ | ⋗ | ⋗ | ||
| # | ⋖ | ⋖ | ⋖ | ⋖ | ≐ |
i(操作数)对一切运算符都 ⋗(它最该先归约);( 对里面一切都 ⋖、# 对里面一切都 ⋖;* ⋗ + 体现"乘优先于加"。分析规则:比较"栈顶终结符"与"当前输入终结符"——遇 ⋖ 或 ≐ 就移进,遇 ⋗ 就归约(归约被 ⋖…⋗ 夹住的最左素短语)。简析 i+i#(N 代表归约出的非终结符):
# ⋖ i 移进 → #i ; i ⋗ + 归约 i → #N #(N) ⋖ + 移进 → #N+ ; + ⋖ i 移进 → #N+i i ⋗ # 归约 i → #N+N ; + ⋗ # 归约 N+N → #N # ≐ # 接受 ✔
优先函数 f、g:用两个数值函数代替整张关系表(省空间)。对应关系:
a ⋖ b ⟺ f(a) < g(b) a ≐ b ⟺ f(a) = g(b) a ⋗ b ⟺ f(a) > g(b)
构造法(图法):为每个终结符设 fa、ga 两个结点;按关系连边后取最长路径长度作函数值。缺点:本来"无关系(空格)"的两个终结符,被函数强行比出了大小,损失了查错能力。
i+i*i# 的完整分析过程,跟我说,我马上给你逐步推。