首页 > 解决方案 > 使用 lark 解析器(ebnf 语法)解析罗马数字时出现 UnexpectedCharacters 错误

问题描述

我在 lark-parser 中使用以下语法来解析字母和罗马数字。语法如下:

DIGIT: "0".."9"
INT: DIGIT+
_L_PAREN: "("
_R_PAREN: ")"
LCASE_LETTER: "a".."z"
ROMAN_NUMERALS: "viii" | "vii" | "iii" | "ii" | "ix" | "vi" | "iv" | "v" | "i" | "x"


?start: qns_num qns_alphabet  qns_part
qns_num: INT?
qns_alphabet: _L_PAREN LCASE_LETTER _R_PAREN | LCASE_LETTER _R_PAREN | LCASE_LETTER?
qns_part: _L_PAREN ROMAN_NUMERALS _R_PAREN | ROMAN_NUMERALS _R_PAREN | ROMAN_NUMERALS?

当我使用此规则并解析以下文本时,出现异常:

# lark.exceptions.UnexpectedCharacters: No terminal defined for 'i' at line 1 col 5
# 10i)i)
#     ^
result = Lark(grammar, parser='lalr').parse("10i)i)")

对于我的一生,我想不出为什么这会引发异常。但这很好:

result = Lark(grammar, parser='lalr').parse("10(i)(i)")  # no error

标签: pythonparsingebnflark-parser

解决方案


发生这种情况的原因是因为两个规则都可以为空,这导致词法分析器总是跳过其中一个以匹配具有更高优先级的终端。

一条规则为空而第二条规则匹配,解析器需要一个 EOF,而不是更多的输入。( 的引入强制规则不为空。

因此,更改 LCASE_LETTER 的优先级将无济于事。但不允许第一条规则为空意志。

Earley 算法将知道如何自动解决这种歧义。

lark-parser我在github 页面上问了同样的问题。从那里回答。


推荐阅读