为每个非终结符写一个(可能递归调用的)子程序,负责识别该非终结符能推出的串[1]。
对文法的要求:无左递归、无回溯(即适合 LL(1))。否则:左递归 → 无限递归;有公共左因子 → 不知走哪条。
按产生式右部从左到右处理每个符号:
· 遇终结符 → 调用 match(与当前输入符比较,相符就读下一个,不符报错);
· 遇非终结符 → 调用它的子程序;
· 有多个候选 → 看当前输入符落在哪个候选的 FIRST 集,选那条分支;
· ε 产生式 → 不消耗输入、直接返回(由当前符/FOLLOW 决定走 ε)。
// sym = 当前输入单词;advance() = 读入下一个单词
procedure E: // E → T E′
T; Eprime;
procedure Eprime: // E′ → + T E′ | ε
if sym = '+' then { advance(); T; Eprime; }
// 否则走 ε:什么都不做,直接返回
procedure T: // T → F T′
F; Tprime;
procedure Tprime: // T′ → * F T′ | ε
if sym = '*' then { advance(); F; Tprime; }
// 否则走 ε
procedure F: // F → (E) | i
if sym = 'i' then advance();
else if sym = '(' then {
advance(); E;
if sym = ')' then advance(); else error();
}
else error();
advance、非终结符就调用同名过程、| 用 if 当前符 选分支、ε 就是"啥也不干返回"。S→(L)|a, L→L,S|S(先消左递归)写递归下降,写完发我看。