购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.3 二义性文法

当一个字符串可以用多种方式解析时,文法就是 二义性 的。例如,考虑字符串'1-2+3'。使用我们的语法初稿,可以用两种不同的方式解析这个字符串,得到如图3.2所示的两棵解析树。这个例子是有问题的,因为虽然正确答案是2,但依照第二棵解析树计算会得到-4。

图3.2 '1-2+3'的两棵解析树

为解决这个问题,我们可以更改文法,以更细粒度的方式对语法进行分类。在这种情况下,当右边的子项是加法时,我们希望不允许应用规则exp: exp "-"exp。为此,我们可以将"-"后面的exp替换为非终结符,该非终结符对除加法之外的所有表达式进行分类,如下所示。

然而,语法中仍然存在一些歧义。例如,字符串'1-2-3'仍然可以两种不同的方式解析,即'(1-2)-3'(正确)或'1-(2-3)'(不正确)。也就是说,减法是左结合的。同样,Python中的加法也是左结合的。我们还需要考虑取负运算与加法和减法的相互作用。我们应该如何解析'-1+2'?取负运算的 优先级 高于加法和减法,因此'-1+2'的解析应与'(-1)+2'相同,而不是'-(1+2)'。图3.3中的文法通过对所有其他表达式使用非终结符exp_hi来处理加法和减法的结合性,并对加法和减法规则中的第二个子表达式使用exp_hi。此外,取负运算使用exp_hi作为其子项。

图3.3 L Int 的非二义性Lark语法

对于具有更多运算符和更多优先级的语言,必须将非终结符exp细化为多个非终结符,每个优先级对应一个非终结符。 V1Gww+U4wLCDSf/N4CxrtyrT/mFWU/PnKxl+XATFNMTrZDfOW+8ETP65ARKFgUzq

点击中间区域
呼出菜单
上一章
目录
下一章
×