初学者问题:"No terminal defined for 'i' at line 2 col 1 int "i" 10" Lark

Beginner Question: "No terminal defined for 'i' at line 2 col 1 int "i" 10" Lark

我是 lark 的新手,我正在尝试创建一个简单的解析器,但我对一个看似简单的问题感到厌烦,为什么“No terminal defined for 'i' at line 2 col 1 int”我“10”出现了吗?这是我的语法:

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”周围的引号,因为当我删除它们时,它们不再成为转义字符串。

如果您阅读完整的错误消息,您会发现唯一预期的令牌是 <END-OF-FILE>。这意味着输入的内容多于语法消耗的内容。我假设您想要的是尽可能频繁地解析 start 。这是通过 ebnf 中的运算符实现的,* 表示 'repeat zero or more times',+ 表示 'repeat one or more times'。因此要修正你的语法:

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"

另请注意,我还做了一些其他更改:我将 set_* 中的第一个 STRING 替换为也从 common 导入的 NAME。这就是我假设你想要的第二个问题。

我还删除了 set_* 中的 " "。既然你 %ignore 他们,这不是必需的,它可能会在将来引起问题。