解析特例

时间:2014-09-18 15:21:17

标签: parsing context-free-grammar peg ll lr

如果我理解正确,解析会将一系列符号转换为树。我的问题是,是否可以使用一些标准程序(LR,LL,PEG,..?)来解析以下两个例子,或者是否有必要手工编写专门的解析器?

  1. Python源代码,即空白缩进块
  2. 我想我在某处读到了解析器跟踪前导空格的数量,并假装用大括号替换它们来划分块。它是否从根本上是必需的,因为标准的解析技术不够强大或是出于性能原因?

    1. PNG图像格式,其中块以标题和块大小开头,之后存在块的内容
    2. 内容可能包含类似某些标题的字节,因此必须“知道”下一个x字节不被“解析”,即应该跳过它们。如何用PEG表达这一点?换句话说,“结束括号”由内容的长度表示。

2 个答案:

答案 0 :(得分:0)

实际上,几乎所有的解析器构造都需要在边缘附近进行一些巧妙的破解,以克服解析机制的局限性。

纯上下文解析器不能做Python;您列出的所有解析器技术都比纯上下文更弱,因此他们也无法做到。词法分析器中的hack用于跟踪缩进并生成INDENT / DEDENT标记,将缩进问题转换为明确的“括号”,这可以通过无上下文解析器轻松处理。

大多数二进制文件也无法处理,因为它们通常在某处包含长度为N的列表,其中N是在遇到列表主体之前提供的(这是您给出的一种示例)。再一次,你可以通过更复杂的黑客来解决这个问题。必须保留一堆嵌套列表长度,并且解析器必须在从一个列表元素移动到下一个列表元素时发出信号。最顶层长度计数器递减,解析器返回信号“reduce”或“shift”。其他更复杂的链接结构通常很难以这种方式解析。让解析器以这种方式合作并不总是那么容易。

答案 1 :(得分:0)

问题中的两个示例都没有上下文,因此严格来说,它们无法使用无上下文语法进行解析。但实际上,它们都很容易解析。

python算法在Python reference manual中有详细描述(尽管你需要在上下文中阅读。)所描述的是一个预处理步骤,其中一行开头的空格被系统地替换使用INDENTDEDENT令牌。

澄清一下:这不是一个真正的预处理步骤,重要的是要注意它在隐式和显式行连接之后发生。 (参考手册中有前面的部分描述了这些过程。)特别是,行在括号,大括号和括号内隐式连接,因此该过程与解析交织在一起。

实际上,线连接和压痕算法都可以通过编程方式完成;通常,这些将在自定义扫描程序(tokenizer)内完成,该扫描程序维护括号和缩进级别的堆栈。然后可以使用正常的无上下文算法解析令牌流,但令牌化器 - 尽管它可能使用正则表达式 - 需要上下文敏感的逻辑(例如,计算空间)。 [注1]

类似地,包含显式大小的格式(例如大多数序列化格式,包括PNG文件,Google protobufs和HTTP分块编码)不是无上下文的,但显然很容易标记化,因为tokenizer只需读取长度然后读取那么多字节。

有各种各样的上下文敏感形式,这些形式肯定有其用途,但在实际解析中,最常见的策略是使用图灵等效形式(如任何编程语言,可能用扫描仪生成器增强)像flex)用于标记化器,以及用于解析器的无上下文形式。 [注2]


备注:

  1. 由于无上下文语法可以接受某些类别的协议,因此Python缩进不是无上下文可能不会立即显而易见。例如,{ωω-1 | ω∈Σ*}(所有偶数长度的回文的语言)都是无上下文的,{anbn}也是如此。

    但是,这些示例无法扩展,因为在无上下文语言中唯一可能的计数协议是包围。因此,虽然回文是无上下文的(您可以使用单个堆栈实现检查),但显然非常相似的{ωω | ω∈Σ*}不是,{anbncn}

  2. 一种这样的形式主义是“常规”表达中的反向引用,这可能在某些PEG实现中可用。反向引用允许表达各种上下文相关语言,但不允许表达所有上下文无关语言。不幸的是,带有反向引用的正则表达式在实践中确实很糟糕,因为确定字符串是否与具有反向引用的正则表达式匹配的问题是NP完成的。您可能会在姐妹SE网站上发现有趣的this question。 (并且您可能希望以可在该网站上提出的方式重新表述您的问题,http://cs.stackexchange.com。)