代码之家  ›  专栏  ›  技术社区  ›  Ben Karel

形式语法能力的实际后果?

  •  14
  • Ben Karel  · 技术社区  · 16 年前

    每个本科生对编译器课程的介绍回顾了上下文无关语法的常见实现子集:ll(k)、slr(k)、lalr(k)、lr(k)。我们也被教导,对于任何给定的k,这些语法中的每一个都是下一个的子集。

    我从未见过这样一个解释:什么样的编程语言句法特征可能需要转移到另一个语言类。对GLR解析器有明显的实用动机,即在解析C++时避免解析器和符号表的不一致。但是,两个“标准”类(ll和lr)之间的区别是什么呢?

    两个问题:

    1. 什么(一般)句法结构可以用lr(k)而不是ll(k)来解析?
    2. 如果有的话,这些结构以什么方式表现为理想的语言结构?

    有一个合理的论据认为,通过使k尽可能小来降低语言能力,因为一种语言需要许多先行标志,这将使人类更难分析,而且机器更难分析。问题(2)隐式地询问相同的推理是否最终在类之间以及类内保持不变。


    编辑:这里有一个例子来说明我正在寻找的答案种类,但是对于常规语言,而不是上下文无关的:

    在描述常规语言时,通常有三个运算符: + , * ? . 现在,您可以删除 + 不降低语言的力量;而不是写作 x+ 你写 xx* 效果是一样的。但是如果 x 是一个大而多毛的表情,两个 X 由于人类的健忘,S可能会随着时间的推移而分化,从而产生一个语法上正确的正则表达式,这与原始作者的意图不符。因此,即使增加 + 不严格加幂,它确实使符号不易出错。

    是否存在具有类似实践(人类)的构造?从lr切换到ll时必须“移除”的效果?

    4 回复  |  直到 16 年前
        1
  •  7
  •   John Clements    16 年前

    解析(我声称)有点像排序:在CS的早期,这个问题是许多思想的焦点,导致了一系列理解良好的解决方案,并产生了一些不错的理论结果。

    我的观点是,我们在编辑课上得到(或给予,给我们中的老师)的图片在某种程度上是对错误问题的一个很好的回答。

    为了更直接地回答您的问题,ll(1)语法不能解析您可能想要解析的所有类型的东西;例如,使用可选“else”的“if”的“natural”公式。

    但是等等!难道我不能把我的语法重新表述成ll(1)语法,然后在源代码树上遍历它来修补它吗?当然可以!在某种程度上,这就是为什么您的解析器在很大程度上没有使用哪种语法的问题。

    另外,当我还是大学生的时候(1990-94),对空格敏感的语法显然是魔鬼的工作;现在,python和haskell的设计将空格敏感重新带到了光明中。另外,packrat解析说“为了检验你理论上的纯洁性:我只是将解析器定义为一组规则,我不在乎我的语法属于哪个类。”(意译)

    总之,我同意你的暗示:在2009年,对ll(k)类和lr(k)类之间的区别的清楚理解,与其说是能够制定和调试语法,让你的解析器生成器感到高兴,还不如说是重要的。

        2
  •  1
  •   Rehno Lindeque    16 年前

    ll和lr之间的区别主要在于先行机制。人们通常说LR解析器携带更多的“上下文”。要实际看到这一点,请考虑以s作为起始符号的递归语法定义:

    A -> Ax | x 
    B -> Ay
    C -> Az
    S -> B | C
    

    当k是一个小的固定值时,解析类似于xxxxy的字符串更适合于lr解析器。然而,现在流行的ll解析器(如antlr)并没有将k限制在如此小的值上,大多数人不再关心。

    我希望这或多或少符合你的问题。当然,Knuth指出,任何明确的上下文无关语言都可以 辨识 通过一些lr(1)语法。然而,在实践中,我们也关注翻译。

    旁注:你也可能喜欢阅读 http://www.antlr.org/article/needlook.html .

    这并没有被证明,但我一直在质疑,类LR的解析是否真的与大脑在阅读某些符号时的工作方式相似。例如,当我们阅读一个英语句子时,很明显我们是从左到右阅读的。但是,考虑下面的模式:

    . ……②……

    我更希望像这样的短图案人们不会从左到右逐字地读“点-点-点-条-点-点-点-点-点-点”,而是以平行或至少某种模糊迭代的方式处理图案。换句话说,我不认为我们必须以从左到右的方式阅读所有模式,使用ll/lr解析器所使用的线性先行。

    此外,如果我们可以使用lr(1)语法描述任何上下文无关的语言,那么很明显,仅仅识别一个字符串和“理解”它是不同的。

        3
  •  0
  •   RCIX    16 年前

    首先,左递归定义在ll(k)语法中是不可能的(据我所知),不了解其他语法。这并不意味着可以定义其他事物 大量的 否则会很痛苦。例如,在左递归语言(伪代码)中,将表达式组合在一起很容易:

    lexer rule expression = other rules
                            | expression
                            | '(' expression ')';
    

    就可以用左递归生成的语法有用的东西而言,简单语法是否算作语法有用?

        4
  •  -1
  •   Ben S    16 年前

    语言的能力不受其语法和语法的限制。

    用ll(k)语法定义任何语言特性都是可能的,它对人类来说可能不是很可读。

    推荐文章