1

我对 lark 很陌生,正在尝试创建一个简单的解析器,但我对一个看似简单的问题感到厌烦,为什么在第 2 行 col 1 int "i" 10" 处没有为 'i' 定义终端?这是我的语法:

start: set_str
     | set_int

COMMENT: ";" /[^\n]/*

set_str: "str " STRING " " STRING
set_int: "int " STRING " " NUMBER

%import common.ESCAPED_STRING -> STRING
%import common.SIGNED_NUMBER  -> NUMBER
%ignore COMMENT
%ignore " "
%ignore "\n"

和文本输入:

int "i" 10 ; this is a comment
str "s" "test"

我是新手,不知道为什么这不起作用,任何提示都可以使用

此外,还有一个较小的第二个问题是有没有办法摆脱“i”和“s”周围的引号,因为当我删除它们时,它们不再成为转义字符串。

4

1 回答 1

0

如果您阅读完整的错误消息,您会看到唯一预期的 Token 是<END-OF-FILE>. 这意味着输入比语法消耗的多。我假设您想要的是start尽可能频繁地解析。这是通过 ebnf 中的运算符实现的,*意思是“重复零次或多次”,+意思是“重复一次或多次”。因此要修正你的语法:

start: (set_str | set_int)+

COMMENT: ";" /[^\n]/*

set_str: "str" NAME STRING
set_int: "int" NAME NUMBER

%import common.ESCAPED_STRING -> STRING
%import common.CNAME-> NAME
%import common.SIGNED_NUMBER  -> NUMBER
%ignore COMMENT
%ignore " "
%ignore "\n"

另请注意,我进行了其他一些更改:我将 中的第一个替换STRINGset_*也来自common导入的NAME。这就是我假设你想要的第二个问题。

我还删除" "set_*. 由于您%ignore是他们,因此不是必需的,并且将来可能会导致问题。

于 2020-12-17T10:19:33.493 回答