你会如何解析缩进(python风格)?

Nul*_*303 9 python parsing indentation lexer

如何定义解析器和词法分析器规则来解析使用缩进来定义范围的语言.

我已经google了一下,通过在词法分析器中生成INDENT和DEDENT令牌,找到了一种解析它的聪明方法.

如果我谈到一些有趣的东西,我会更深入地研究这个问题并发表答案,但我希望看到解决问题的其他方法.

编辑:正如查理指出的,如果不是相同的话,已经有另一个非常相似的线程.我的帖子应该被删除吗?

Cha*_*tin 10

这是一种假设,因为它取决于你的词法分析器和解析器的技术,但最简单的方法似乎是让BEGINBLOCK和ENDBLOCK标记类似于C中的大括号.使用你的词法分析器所需的"越位规则"跟踪一堆压力水平.当缩进级别增加时,为解析器发出BEGINBLOCK; 当缩进级别减小时,从堆栈中发出ENDBLOCK和弹出级别.

这是关于SO 的另一个讨论,顺便说一下.


Igo*_*orK 1

您还可以在词法分析器中的某个位置跟踪第一行前面有多少个 ident 项并将其传递给解析器。最有趣的部分是尝试将其正确传递给解析器:)如果您的解析器使用前瞻(这里我的意思是解析器可能会在真正匹配一个标记之前查询可变数量的标记),那么尝试将其传递给一个全局变量似乎这是一个非常糟糕的主意(因为词法分析器可以在下一行上滑动并更改缩进计数器的值,而解析器仍在尝试解析上一行)。在许多其他情况下,全局变量也是邪恶的;)用缩进计数器以某种方式标记第一行“真实”标记更合理。我无法给你确切的例子(我什至不知道你将使用什么解析器和词法分析器生成器(如果有的话)),但是像在第一行标记上存储数据之类的东西(如果可以的话,可能会不太舒服) t 轻松地从解析器获取此类标记)或保存自定义数据(将标记链接到缩进的映射,其中源代码中的每一行作为索引,缩进值作为元素值)似乎就足够了。这种方法的一个缺点是解析器变得更加复杂,需要区分 ident 值并根据它更改其行为。像 JavaCC 的 LOOKAHEAD({ yourConditionInJava }) 这样的东西可能在这里工作,但这不是一个好主意。您的方法中的许多附加标记似乎使用起来不那么邪恶:)

作为另一种选择,我建议混合使用这两种方法。仅当缩进计数器在下一行更改其值时,您才能生成附加标记。它就像人工的 BEGIN 和 END 令牌。通过这种方式,您可以减少流中从词法分析器输入解析器的“人工”标记的数量。只需调整您的解析器语法即可理解其他标记......

我没有尝试过这个(对此类语言解析没有真正的经验),只是分享我对可能的解决方案的想法。检查此类语言的已构建解析器可能对您非常有价值。开源是你的朋友;)