问题描述
我的任务是解析(和转换)一种计算机语言的代码,它的规则有点奇怪,至少我是这样看的。确切地说,编译器将新行(以及分号)视为语句分隔符,但除此之外(例如在语句内部),编译器将它们视为空格符(空格).
举个例子,这段代码:
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,因为它很重要。)
解决方法
“规范”中的相关引用是这样的:
松鼠程序是一个简单的语句序列。:
stats := stat [';'|'\n'] stats
[...] 语句可以用新行或 ';' 分隔(或者如果在 switch/case 语句中,则用关键字 case
或 default
),两个符号都不是必需的如果语句后跟'}'。
这些是相对复杂的规则,如果换行符也可以在其他地方被忽略,那么它们总体上不是上下文无关的。但是请注意,根据我的理解,文本暗示 ;
或 \n
在其他情况不适用时是必需的。那会使你的例子非法。这可能意味着所写的 BNF 是正确的,例如;
和 \n
都是可选的。在这种情况下,您可以(对于百灵鸟)只需放置一个 %ignore "\n"
语句,它应该就可以正常工作。
此外,如果您都忽略 \n
并在规则中使用它,lark 不应该抱怨:如果有用,它将在规则中匹配它,否则它只会忽略它。但是请注意,如果您使用包含 \n
(例如 WS
或 /\s/
)的终端,这会中断。只需将 \n
作为一个额外的案例。
(对于未来:如果您在 gitter 上询问或至少在那里放一个指向 SO 的链接,您可能会更快地获得对百灵鸟问题的答复。)