【问题标题】:How would you parse indentation (python style)?你将如何解析缩进(python 风格)?
【发布时间】:2008-12-10 16:17:25
【问题描述】:
【问题讨论】:
标签:
python
parsing
indentation
lexer
【解决方案1】:
这是一种假设,因为它取决于您的词法分析器和解析器所使用的技术,但最简单的方法似乎是使用类似于 C 中的大括号的 BEGINBLOCK 和 ENDBLOCK 标记。使用 "offsides rule" 您的lexer 需要跟踪一堆缩进级别。当缩进级别增加时,为解析器发出一个 BEGINBLOCK ;当缩进级别降低时,发出 ENDBLOCK 并从堆栈中弹出级别。
Here's another discussion 这个关于 SO,顺便说一句。
【解决方案2】:
您还可以在词法分析器中的某处跟踪第一行之前有多少标识项并将其传递给解析器。最有趣的部分是尝试正确地将它传递给解析器:) 如果您的解析器使用前瞻(这里我的意思是解析器可能会在它真正匹配甚至一个之前查询可变数量的标记)然后尝试通过一个全局变量传递它似乎这是一个非常糟糕的主意(因为词法分析器可以在下一行滑动并更改缩进计数器的值,而解析器仍在尝试解析前一行)。在许多其他情况下,全局变量也是邪恶的;)以某种方式用缩进计数器标记第一行“真实”标记更合理。我不能给你确切的例子(我什至不知道你将使用什么解析器和词法分析器生成器,如果有的话......)但是像在第一行标记上存储数据之类的东西(如果你可以的话,它可能会不舒服' t 轻松地从解析器获取此类标记)或保存自定义数据(将标记链接到缩进的映射、源代码中的每一行作为索引和缩进值作为元素值的数组)似乎就足够了。这种方法的一个缺点是解析器的额外复杂性,需要区分 ident 值并根据它改变其行为。 JavaCC 的 LOOKAHEAD({ yourConditionInJava }) 之类的东西可能在这里工作,但它不是是一个非常好的主意。您的方法中的许多额外标记似乎不太好用:)
作为另一种选择,我建议将这两种方法混合使用。只有当缩进计数器在下一行更改其值时,您才能生成额外的标记。它就像人工的 BEGIN 和 END 令牌。通过这种方式,您可以减少从词法分析器馈送到解析器的流中的“人工”令牌数量。只有你的解析器语法应该被调整以理解额外的标记......
我没有尝试过(对此类语言解析没有实际经验),只是分享我对可能解决方案的想法。检查已经为这类语言构建的解析器可能对您有很大的价值。开源是你的朋友;)