我正在使用以下格式解析文件:
INT32 price min 10 max 100 alertIfSold ;
min,max和alertIfSold标记都是可选的,可以按任何顺序出现。那是
INT32 price max 100 alertIfSold ;
INT32 price max 100 min 10 alertIfSold ;
INT32 price alertIfSold ;
INT32 price;
都是有效的例子。
以下是我测试的语法的简单版本。 运行python test.py会生成此错误:
lark.common.ParseError:检测到无限递归! (规则 < __ anon_star_1:__ anon_star_1>)
我尝试使用其他语法规则表达相同的可选令牌,结果相似(无限递归)。
表达可选参数的正确语法是什么?
#test.py
from lark import lark
simplified_grammar = """
start: line+
line: TYPE CNAME [MIN MAX ALERT]* ";" -> foo
TYPE: "INT32" | "INT64"
MIN: "min" /[0-9]+/
MAX: "max" /[0-9]+/
ALERT: "alertIfSold"
%import common.CNAME
%import common.WS
%ignore WS
"""
sample = """
INT32 price max 100 alertIfSold ;
INT32 price max 100 min 10 alertIfSold ;
INT32 price alertIfSold ;
INT32 price;
"""
parser = lark.Lark(simplified_grammar)
def main():
parse_tree = parser.parse(sample)
if __name__ == '__main__':
main()
答案 0 :(得分:3)
你想:
line: TYPE CNAME (MIN | MAX | ALERT)* ";" -> foo
(注意:()
代替[]
。)
在lark的EBNF语法中,[item]
表示“可选item
”,item*
表示“item
”的任意数字(可能为零)。因此[item]*
表示“任何数字(可能为零)item
或任何内容”。但“任何数量的无关”都是无限暧昧的;你不知道空字符串中有多少个没有。
由于您实际上并不打算要求条款严格连续出现,您可能一直在考虑
line: TYPE CNAME ([MIN] [MAX] [ALERT])* ";" -> foo
这样会更准确,但它也会产生相同的错误信息。通常,您不能在可以为空的子模式上使用Kleene星。一些EBNF生成器将通过从重复集中移除ε来纠正它(然后使重复作为整体可选),但是云雀不是其中之一。在这种情况下,修复是微不足道的,但在其他情况下,它更令人讨厌。
作为正则表达式,(a* b*)*
,(a? b?)*
和(a|b)*
在他们都识别相同语言的意义上是等效的。但是正则表达式是众所周知的模糊,解析器通常更喜欢明确的语法,或者最坏的是有限模糊的语法。只有最后一个正则表达式属于该类别,并且它是您通常应该选择的表单。