“反向证推导推出运行,对有限推导树作结构归纳。叶规则 $[uXr]\to a$ 本身就是一个真实弹栈动作。一子树规则先执行首动作,再把子树给出的运行放在 $\beta$ 上;两子树规则先把 $…”
形式陈述
给定上下文无关文法
本页把
从左到右读取所有终结符叶,忽略
尚有未展开非终结符叶子的树是部分语法树,其前沿给出一个句型,还不是完整的终结符字符串。树的孩子顺序不可丢掉,否则 ab 与 ba 可能被错误地视为同一产出。
直觉
推导序列记录“先做哪一步替换”,语法树记录“哪一部分由哪条规则产生”。前者包含操作顺序,后者保留最终的层次和分组。两次推导若只是交换彼此独立的子树的展开顺序,可以得到完全相同的树。
每一步推导都能在待展开的叶子处接上对应产生式,逐步建成树;反过来,按某个合法顺序展开树中的非终结符,就能得到产出相同的推导。这解释了上面的等价关系。固定一棵树后,总展开最左非终结符便得到唯一最左推导,总展开最右者则得到唯一最右推导。
例子与边界
从局部产生式还原整个字符串
对文法 aabb 的语法树为:
S
/ | \
a S b
/|\
a S b
|
ε
外层 a a ε b b,删去 aabb。对应推导为
这个例子每一步只有一个待展开的非终结符,适合说明嵌套结构,却不能用来展示“两个独立子树可以交换展开顺序”。
两个不同推导,可以是同一棵树
改用文法
前者先展开
S
/ \
A B
| |
a b
因此,发现两个一般推导序列不足以证明文法有歧义。这里的差别只在完成独立工作的先后,并不改变句子的结构。
真正的歧义:分组发生变化
取文法 a+a*a 有两棵不同的完整语法树:
E E
/ | \ / | \
E + E E * E
| /|\ /|\ |
a E * E E + E a
| | | |
a a a a
左树的根使用加法产生式,右侧子树是乘法,对应分组
这里的括号只用于说明分组,并没有出现在原字符串中。语法树表达组合结构;它是否对应数值加乘、如何求值,还需要给运算符指定语义。
用文法表达优先级
希望乘法比加法结合得更紧,可以把文法分层:
表达式 a+a*a 的右侧乘法必须先组成一个项,再与左侧相加;左递归的结构还确定了同级运算的左结合。括号作为因子允许显式改变分组。
这是一种针对算术表达式的文法设计,不是把任何歧义文法自动变成无歧义文法的通用步骤。解析工具也可以在原文法之外使用优先级、结合性声明来选择解析结果,需要区分“文法本身无歧义”和“解析器有消歧规则”。
推论与应用
语法树也常称为具体语法树。它严格对应所选文法,可能保留括号、分隔符及
从输入串构造本页的树,可以使用预测栈或移进归约栈;若文法有歧义,共享打包森林会在同一输入区间下保留不同分组。类型、变量绑定与符号表信息不会由一棵未加注解的树自动出现,仍需语义动作、属性传播或后续遍历。
对已经给定的候选树,有限树自动机可以自底向上检查固定文法的局部展开。接入固定秩字母表前,需要按“符号、孩子数”区分可能具有不同元数的标签;本页的空产生式仍保留零元的
Chomsky 范式的非终结符展开主要为
参考资料
- Stanford CS143, Introduction to Parsing,Derivations and Parse Trees、Ambiguity、Precedence and Associativity 各节。
- Michael Sipser, Introduction to the Theory of Computation, 3rd ed., Cengage, 2013,§2.1 “Context-Free Grammars”,语法树、歧义与 Chomsky 范式。
- John E. Hopcroft, Rajeev Motwani, and Jeffrey D. Ullman, Introduction to Automata Theory, Languages, and Computation, 3rd ed., Pearson, 2006,Chapter 5 “Context-Free Grammars and Languages”。