一种离线语言是指在该语言中,声明的范围(块)由缩进表示。
...例如Python、Boo、Nemerle、YAML等语言。
那么我的问题是:我应该如何解析这些语言?如何解决制表符与空格的问题(两个制表符或8个空格是否等效)?解析器生成器是否有助于此,还是我必须手动编写词法分析器/语法分析器?
一种离线语言是指在该语言中,声明的范围(块)由缩进表示。
...例如Python、Boo、Nemerle、YAML等语言。
那么我的问题是:我应该如何解析这些语言?如何解决制表符与空格的问题(两个制表符或8个空格是否等效)?解析器生成器是否有助于此,还是我必须手动编写词法分析器/语法分析器?
(aaa bb) cc
e fffff (ggg hhh) iii
jjj kkk
ddd
这里将aaa
应用于bb
。结果是一个三元函数,它被应用于参数cc
、应用于一个参数的e
和ddd
。请注意,应用是基于列对齐而不是X空格的。
解析器可能也可以更简单。
关于制表符和空格,您有几个选项:禁止混合使用制表符和空格,假定制表符与空格的比例固定,或允许程序员根据每个项目或每个源文件的情况来决定(一种类似于“#pragma tab(4)”样式指令,以允许使用制表符和/或更改它们所代表的空格数)。
ANTLR 3等解析器生成器可以轻松处理此问题;我自己也玩过一个示例,编译到其C#目标。DirkGently's answer中的链接解释了Python算法,可直接转换为代码。我的方法只是为空格和换行符定义单独的标记,并覆盖了词法分析器使用的“发出标记”函数,以便在运行时插入额外的缩进/取消缩进标记。这比我看到的其他方法要简单得多,但两种方法都很有效。
"指导"阶段(或“折叠”阶段)获取标记并基本上生成推送和弹出,以创建树形数据结构的指令。它实际上是将列表折叠成树。
最终的"树化"阶段获取树形指令并实际构建树。事实证明这相当困难,需要进行思维上的体操来考虑如何将标记列表转换为树。我整个周末都在尝试使其工作,但仍然有很长的路要走,才能使输出树与推送和弹出正确对齐。
尽管代码水平不算太高,但它应该作为构建基于缩进的解析器的现实世界示例。
我自己找到了一种解决方案,就是将代码分析成嵌套树形块。对于括号部分,我只是使用了普通的方法。