如何在语法中添加一点上下文?

How to add a small bit of context in a grammar?

我的任务是解析(和转换)一种计算机语言的代码,它的规则有点奇怪,至少我是这样看的。确切地说,编译器将新行(以及分号)视为 语句分隔符 ,但除此之外(例如在语句内部),它将它们视为 间隔符 (空格)。

例如,此代码:

try
    local x = 5 / 0
catch (i)
    print(i + "\n")

证明等价于此:

try local x = 5 / 0 catch (i) print(i + "\n")

我不知道如何在 EBNF 中表达这样的规则,或者特别是在 Lark EBNF 方言中。我的意思是以一种明智的方式。我可能可以在所有语句中定义所有可能的换行符位置,但这会很麻烦且容易出错。

我希望找到一种根据上下文处理换行符的方法。是否有经过验证的方法,最好在 Python/Lark 域内?如果我必须为此目的修改解析器,那么我应该从哪里开始?

或者,如果我特别误解了这种语言或一般机器语言解析中的某些内容,或者我对问题的陈述是错误的,我也很乐意接受教育。

(正如您可能猜到的,所讨论的语言具有经过充分验证的实现,但没有正式定义的语法。此外,它是 Squirrel,尽管它很重要。)

“规范”中的相关引用是这样的:

A squirrel program is a simple sequence of statements.:

stats := stat [';'|'\n'] stats

[...] Statements can be separated with a new line or ‘;’ (or with the keywords case or default if inside a switch/case statement), both symbols are not required if the statement is followed by ‘}’.

这些是相对复杂的规则,如果换行符也可以在其他地方被忽略,那么它们的整体就不是上下文无关的。但是请注意,根据我的理解,文本暗示在没有其他情况适用时需要 ;\n。那将使您的示例非法。这可能意味着所写的 BNF 是正确的,例如;\n 都是可选的。在那种情况下,你可以(为了百灵鸟)只输入一个 %ignore "\n" 语句,它 应该 工作正常。

此外,如果您同时忽略 \n 并在规则中使用它,百灵鸟不应该抱怨:有用的地方它会在规则中匹配它,否则它只会忽略它。但是请注意,如果您使用包含 \n(例如 WS/\s/)的终端,这会中断。只是有 \n 作为一个额外的案例。

(对于未来:如果您在 gitter 上提问或至少在 SO 上添加 link,您可能会得到更快的百灵问题回复。)