Lexers and parsers are typically defined separately and connected by a token stream. This separate definition is important for modularity and reduces the potential for parsing ambiguity. However, materializing tokens as data structures and case-switching on tokens comes with a cost. We show how to fuse separately-defined lexers and parsers, drastically improving performance without compromising modularity or increasing ambiguity. We propose a deterministic variant of Greibach Normal Form that ensures deterministic parsing with a single token of lookahead and makes fusion strikingly simple, and prove that normalizing context free expressions into the deterministic normal form is semantics-preserving. Our staged parser combinator library, flap, provides a standard interface, but generates specialized token-free code that runs two to six times faster than ocamlyacc on a range of benchmarks.
翻译:词法分析器和解析器通常是分别定义的,并通过一个标记流相连。这种分离的定义对于模块化很重要,并减少了解析歧义的可能性。然而,将标记实体化为数据结构并在标记上进行情况切换是有代价的。我们展示了如何融合分别定义的词法分析器和解析器,极大地提高了性能,而不影响模块化或增加歧义。我们提出了 Greibach 标准格式的确定性变体,它确保以单个标记的先行模式进行确定性解析,并使融合变得非常简单,并证明将上下文无关表达式标准化为确定性标准格式是语义保持的。我们的分阶段解析组合库 flap 提供了标准接口,但生成专业的零标记代码,其在一系列基准测试中的运行速度比 ocamlyacc 快两到六倍。