我一直在努力寻找一种递归下降解析器算法,该算法也适用于带回溯的缩进。 但我一直在为此找到麻烦的解决方案。
是否有任何资源也可以处理缩进?
由于
答案 0 :(得分:3)
根据你的问题,我假设你正在为缩进敏感语言编写自己的递归下降解析器。
我之前尝试过基于缩进的语言,我通过一个跟踪当前缩进级别的状态和两个与缩进匹配的终端来解决问题。它们都与缩进单位(比如两个空格或制表符)匹配并计算它们。我们调用匹配的缩进级别matched_indentation
和当前缩进级别expected_indentation
。
对于第一个,我们称之为indent
:
matched_indentation < expected_indentation
,则为dedent
,但匹配失败。matched_indentation == expected_indentation
,则匹配成功。匹配器使用缩进。matched_indentation > expected_indentation
,你有一个语法错误(不知道的缩进)并且应该处理它(抛出异常或其他东西)。对于第二个,我们称之为dedent
:
如果matched_indentation < expected_indentation
,则匹配成功。您将expected_indentation
减少一个,但不消耗输入。这样您就可以链接多个dedent
终端以关闭多个范围。
如果matched_indentation == expected_indentation
,则匹配成功,这次您使用输入(这是最后一个dedent
终端,所有范围都已关闭)。
如果matched_indentation > expected_indentation
,则匹配失败,此处您没有dedent
。
您希望缩进增加的那些终端和非终端应该将expected_indentation
增加一个。
假设您想要实现类似python的if语句(我将使用类似EBNF的表示法),它看起来像这样:
indented_statement : indent statement newline;
if_statement : 'if' condition ':' newline indented_statement+ dedent ;
现在让我们看看以下代码,并假设if_statement
是statement
规则的一部分:
1|if cond1: <- expected_indentation = 0, matched_indentation = 0
2| if cond2: <- expected_indentation = 1, matched_indentation = 1
3| statement1 <- expected_indentation = 2, matched_indentation = 2
4| statement2 <- expected_indentation = 2, matched_indentation = 2
5| <- expected_indentation = 2, matched_indentation = 0
indent
终端dedent
终端,关闭两个范围,并生成expected_indentation = 0
您应该注意的一件事是放置indent
和dedent
终端的位置。在这种情况下,我们在if_statement
规则中不需要一个,因为它是statement
,而indented_statement
已经预期缩进。
还要注意你如何对待换行。一种选择是将它们作为一种语句终止符使用,另一种选择是将它们放在缩进之前,因此请选择最适合您的语句。