Syntax Analysis
Syntax Analysis
建立语法树的过程
Top-Down Parsing
用先序构造一个语法树
代码方面举个例子,比如对于S->c A b
bool S() {
if (*cursor == 'c') cursor++; // 匹配 'c'
else return false;
if (!A()) return false; // 调用函数 A()
if (*cursor == 'b') cursor++; // 匹配 'b'
else return false;
return true;
}
但是这样可能会出现一些匹配的问题,比如多种可选匹配组合下,如果按照这个代码跑就会漏掉一些情况,所以需要回溯等方法来处理 再比如可能会出现死循环
LL(1) 是一种具体的预测解析方法: 无二义性 无死循环
- 第一个 L 表示从左到右扫描输入字符串。
- 第二个 L 表示使用最左推导(leftmost derivation),即在每一步推导时,总是展开最左边的非终结符。
- 1 表示在每一步解析时使用一个输入符号进行前瞻,以决定下一步的解析动作
FIRST(A):FIRST(A) 是一个集合,包含非终结符A能够推导出的所有可能的开头终结符。如果A能够推导出空字符串ε,那么FIRST(A)也包含ε
- 如果A是一个终结符,那么FIRST(A) = {A}。
- 如果A是一个非终结符,那么:
-
- 对于A的每个产生式A → α,将α的第一个符号的FIRST集加入FIRST(A)中,直到遇到一个不包含ε的符号。
- 如果α可以推导出ε,那么将ε加入FIRST(A)。
FOLLOW(A):FOLLOW(A) 是一个集合,包含所有可能出现在非终结符A后面的终结符。这些终结符是在语法树中直接跟在A后面出现的。
- 初始化FOLLOW(开始符号)为{},其中是输入结束标志。
- 对于每个产生式A → αBβ:
-
- 将FIRST(β)中的所有终结符(不包括ε)加入FOLLOW(B)。
- 如果β可以推导出ε,或者β是空,那么将FOLLOW(A)中的所有符号加入FOLLOW(B)。
- 重复上述步骤直到FOLLOW集不再变化。
Bottom-up Parsing
后序遍历
LR(0) 解析的特点
- 从左到右扫描:LR(0) 解析器从左到右扫描输入字符串。
- 最右推导:LR(0) 解析器使用最右推导(right-most derivation),即在每一步推导时,总是展开最右边的非终结符。
- 零个符号的前瞻:LR(0) 解析器在解析过程中不需要使用前瞻符号来做出决策。这意味着解析表的构造相对简单,但适用范围有限。