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

时间:2008-12-10 16:17:26

标签: python parsing indentation lexer

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

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

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

编辑: 正如查理指出的那样,there is already another thread very similar if not the same.我的帖子应该被删除吗?

2 个答案:

答案 0 :(得分:10)

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

"offsides rule"关于SO,顺便说一下。

答案 1 :(得分:1)

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

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

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