理解和编写解析器

时间:2016-04-02 15:59:47

标签: parsing

我正在编写一个程序,要求我创建我的第一个真正的,有点复杂的解析器。我想了解解析算法的存在,以及如何创建"语法"。所以我的问题如下:

1)如何创建解析器可以理解的正式语法?语法的基本组成部分是什么?

2)存在哪些解析算法,以及在解析时各自超出哪种输入?

3)鉴于上述问题的广泛性,我可以阅读哪些好的参考资料来理解问题1和2的答案?

我正在寻找更多关于我需要的关键字/主题领域的概述,以便我自己查看详细信息。谢谢大家!

1 个答案:

答案 0 :(得分:2)

您通常会编写无上下文语法 G来描述某种形式语言 L(例如,所有语法上有效的C语言集)程序)这只是一组特定字母表上的字符串(想想所有格式良好的C程序;或者所有格式良好的HTML文档;或者所有格式良好的MARKDOWN帖子;所有这些都是有限字符串集合ASCII字符集的某些子集)。之后,您为给定的语法提出了解析器 - 也就是说,给定字符串w的算法决定是否可以派生字符串w通过语法G。 (例如,grammar of the C11 language描述了所有格式良好的C程序集。)

某些类型的语法允许简单实现解析器。在实践中经常使用的语法示例是LL grammarsLL语法的一个特殊子集,称为LL(1)语法,具有以线性时间运行的解析器(在我们解析的字符串长度中是线性的)。

有更多通用的解析算法 - 最值得注意的是Early parserCYK algorithm ---将inpuit作为字符串w和语法G和及时决定O(|w|^3)字符w是否可由语法G推导出来。 (请注意这是多么酷:算法将语法作为一种方法。但我不认为这是在实践中使用。)

我前段时间用Java实现了Early parser。如果您有兴趣,则代码为available on GitHub

有关整个过程的具体示例,请考虑括号()(())((()))()(())()等所有平衡字符串的语言。我们可以使用以下语境对其进行描述 - 自由语法:

S -> (S) | SS | eps

其中eps是空产品。例如,我们可以按如下方式派生字符串(())()S => SS => (S)S => ((S))S => (())S => (())(S) => (())()。我们可以轻松地为这个语法实现一个解析器(左为练习: - )。

很好的参考是所谓的龙书:Aho等人的Compilers: Principles, Techniques, and Tools。它涵盖了所有重要主题。另一个很好的参考是Hopcroft等人的经典着作Introduction to Automata Theory, Languages, and Computation