有多种方法可以将 CFG 转换为进行实际解析的代码,每种方法都有其优点和缺点。
一些算法,如 CYK 算法、Unger 算法和(我个人最喜欢的)Earley 算法可以将任意 CFG 和字符串作为输入,然后使用动态编程来确定该字符串的解析树(如果存在)。这些算法的操作与典型的下推自动机不同,因为它们通过填写值表来工作,同时一次处理一个字符。
一些解析算法,尤其是 LR(1) 和一般的 LR 解析器家族,更直接地维护解析堆栈并使用有限状态控制来驱动解析器。但是,LR(1) 解析器不能处理所有可能的 CFG——它们只能处理确定性 CFG——但是像 GLR 解析器这样的变体可以通过基本上并行运行多个堆栈来处理所有语法。编译器生成工具 bison 和 yacc 在这个系列中生成解析器,如果您看看它们的输入文件是如何工作的,您就会了解 CFG 是如何在软件中编码的。
LL(1) 解析器和简单回溯解析器自上而下工作,通常使用堆栈(通常是运行时调用堆栈)来解析输入字符串。但是,他们无法处理所有语法。ANTLR 解析器生成器生成这个系列的解析器。
Packrat 解析器通过使用修改过的 CFG 来工作,这些 CFG 对尝试的优先级进行编码。使用这些解析器的代码往往会密切反映语法的形状。解析器组合器是另一种现代技术,其中解析逻辑看起来很像 CFG。
如果您有兴趣了解这方面的更多信息,我建议您参加编译器课程或阅读 Grune 和 Jacobs 的“Parsing Techniques: A Practical Guide”。