[英]Lark how to describe a series of optional tokens
我正在解析的文件格式可以包括:
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()
你要:
line: TYPE CNAME (MIN | MAX | ALERT)* ";" -> foo
(注意:( ()
代替[]
。)
在雲雀的EBNF語法, [item]
的意思是“一個可選item
”和item*
“的任何數目(可能為零)的裝置item
”。 所以[item]*
表示“任一的任何數目(可能為零) item
或全無”。 但是“無數無數”是無限模棱兩可的。 您無法判斷一個空字符串中有多少個空字符。
由於您實際上並不打算要求這些條款嚴格連續出現,因此您可能一直在考慮
line: TYPE CNAME ([MIN] [MAX] [ALERT])* ";" -> foo
那本來會更准確,但也會產生相同的錯誤消息。 通常,不能在可為空的子模式上使用Kleene星。 一些EBNF生成器會通過從重復集中刪除ε(然后將整個重復設為可選)來糾正這一問題,但百靈鳥不是其中之一。 在這種情況下,修復很簡單,但在其他情況下更令人討厭。
作為正則表達式, (a* b*)*
, (a? b?)*
和(a|b)*
在它們都識別相同語言的意義上是等效的。 但是正則表達式眾所周知是模棱兩可的,並且解析器通常更喜歡模棱兩可的語法,或者最糟糕的是有限的模棱兩可的語法。 只有最后一個正則表達式屬於該類別,並且它通常是您應首選的形式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.