为什么解析器生成器而不仅仅是可配置解析器?

时间:2012-01-08 18:59:08

标签: parsing lexical-analysis

标题总结了它。据推测,任何可以通过源代码生成解析器生成器(基本上将要解析的语法硬编码到程序中)完成的任何事情都可以通过可配置的解析器来完成(这将保持语法准备) - 经过软编码作为数据结构)。

我认为硬编码的代码生成解析器会有一个较低级别的间接性能,但是必须编译和运行它(或者用exec()动态语言)和代码生成的整体笨拙似乎是一个很大的缺点。代码生成您的解析器还有其他任何我不知道的好处吗?

我看到代码生成的大多数地方都是为了解决语言的元编程能力的限制(即Web框架,AOP,与数据库的接口),但整个lex-parse的东西看起来非常简单和静态,不需要从代码生成中获得任何额外的元编程动态。是什么赋予了?性能优势是否很好?

1 个答案:

答案 0 :(得分:12)

如果您只想要一个可以通过处理语法规则来配置的解析器,那么就可以完成。只有一组规则,Earley解析器才会解析任何无上下文的语言。价格是重要的执行时间:O(N ^ 3),其中N是输入的长度。如果N很大(就像许多可解析的实体一样),你可以用非常慢的解析结束。

这就是解析器生成器(PG)的原因。如果解析大量文档,慢速解析就是坏消息。编译器是人们解析大量文档的程序,没有程序员(或他的经理)希望程序员等待编译器。还有很多其他要解析的东西:SQL查询,JSON文档......所有这些都有这个"没有人愿意等待"属性。

PG做的是做出许多必须在运行时发生的决定(例如,对于Earley解析器),并在解析器生成时预先计算这些结果。因此,LALR(1)PG(例如,Bison)将产生在O(N)时间内运行的解析器,并且在实际情况下显然更快。 (ANTLR对LL(k)解析器执行类似的操作)。如果您想要通常线性的完全无上下文解析,您可以使用名为GLR parsing的LR解析变体;这可以为您带来“可配置的”#34; (Earley)解析器,具有更好的典型性能。

这种预先计算的想法通常被称为partial evaluation,也就是说,给定函数F(x,y),并且知道x总是某个常数x_0,计算一个新函数F&#39 ;(y)= F(x0,y),其中仅依赖于x的值的决策和计算是预先计算的。 F'通常运行速度比F快很多。在我们的例子中,F类似于通用解析(例如,Earley解析器),x是语法参数,x0是特定语法,而F'是一些解析器基础结构P和由PG计算的附加代码/表,使得F' = PG(x)+ P.

在你的问题的评论中,似乎有一些兴趣,为什么一个人不能在运行时运行解析器生成器。简单的答案是,它支付了你想要在运行时摆脱的开销成本的很大一部分。