📅  最后修改于: 2023-12-03 14:55:55.086000             🧑  作者: Mango
在计算机科学中,歧义语法是指能够被多个解释所理解的语法。这种语法会引起诸如语法分析错误、语言特征模糊不清、程序行为不一致等一系列的问题。下面将介绍常见的歧义语法及其解决方法。
上下文无关语法是一种描述语言结构的形式化语法。它的主要特点是每个非终结符都可以通过语法规则来转化成一个或多个符号串,而不受其他符号串所包含的语言环境的影响。上下文无关语法中常见的歧义语法包括二义文法和移进-规约歧义。
二义文法指的是在具有相同语法规则的情况下,存在着两种或多种不同的语法树表示相同的输入串的情况。例如:
<expr> ::= <num> | '(' <expr> <op> <expr> ')'
<op> ::= '+' | '-'
<num> ::= '0' | '1' | ... | '9'
对于表达式 1 + 2 - 3
,可以存在两种不同的语法树表示。一种是把 1 + 2
看作一个整体再减去 3
,另一种是先求得 1 + 2 - 3
的左部 1 + 2
,然后减去 3
,如下所示。
可以发现,二义文法会导致程序的行为存在不确定性,而且在语法分析过程中容易出现错误。解决二义文法的方法通常是消除二义性,例如将规则改写为左递归的形式。
移进-规约歧义指的是在使用自下而上的语法分析算法(如LR分析器)时,由于存在多个规约动作可以被选择,造成决策歧义的情况。例如:
Grammar:
S -> S S + | S S * | a
Tokens:
a + a * a
Parse table:
a * + $
0 0 1 1 0
1 s2 0 s3 0
2 r3 r3 s4 0
3 s2 s5 s3 0
4 r2 r2 r2 r2
5 r1 r1 r1 r1
Action:
0 a s2
0 $ acc
1 a s3
1 $ r3
2 + r3
2 * s4
3 + s5
3 * r2
4 a s2
4 $ r1
5 + r1
5 * r1
在使用上述语法分析器解析表达式 a + a * a
时,存在两种不同的规约路径,分别为 S S *
和 S +
。这会导致解析结果的不确定性。解决移进-规约歧义的方法包括添加优先级和结合性规则、使用GLR分析器等。
上下文有关语法是一种描述语言结构的形式化语法。它的特点是规则中包含符号串的上下文信息。因此,上下文有关语法相对于上下文无关语法可以描述更为丰富的语言。上下文有关语法中常见的歧义语法包括二义句号和空格理解歧义。
二义句号指的是一句话存在两种或多种不同的语义解释的情况。例如:
规则:NP VP
S -> NP VP
NP -> 名词
NP -> NP 的 NP
VP -> 动词 NP
VP -> VP 和 VP
名词 -> 士兵 | 小书包 | 篮球
动词 -> 投篮 | 投掷 | 奔跑
对于句子 小书包的士兵投掷和奔跑
,可以存在两种不同的词法划分和语法树表示。一种将 小书包的士兵
视为一个名词短语,投掷和奔跑
视为一个复合动词短语,另一种则相反,如下所示。
解决二义句号的方法包括限制语言特征(如限制名词短语只能由一个名词构成),或通过手工编写语义动作对语法树进行进一步的语义分析。
空格理解歧义指的是仅仅依靠空格进行理解时存在歧义的情况。例如:
规则:S -> aSb
S -> ε
对于输入 a b
,可以存在两种不同的符号串生成方式,分别为 a ε b
和 a S b
。这会导致程序行为的不确定性。解决空格理解歧义的方法包括使用其他的语言特征(如括号)进行限制,或者对输入进行更加严格的形式化限制。
在编写程序的过程中,需要避免使用歧义语法,因为它会造成程序的行为不确定、程序逻辑不清晰等问题。为了消除歧义语法,可以通过消除二义性、添加语法限制、手动编写语义动作等方式进行解决。因此,对于开发人员来说,必须要了解歧义语法的相关知识,在编写程序时避免使用歧义语法,同时通过使用合适的语言特征和工具,消除存在的歧义。