Неожиданные символы Ошибка при разборе римской цифры с использованием синтаксического анализатора lark (грамматика ebnf) - PullRequest
0 голосов
/ 04 октября 2019

Я использую следующую грамматику в 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

1 Ответ

0 голосов
/ 04 октября 2019

Причина, по которой это происходит, заключается в том, что оба правила могут быть пустыми, что приводит к тому, что лексер всегда перепрыгивает через одно из них, чтобы сопоставить терминал с более высоким приоритетом.

С одним правиломпустой и второй совпадает, синтаксический анализатор ожидает EOF, не больше ввода. Введение (заставляет правило не быть пустым.

Таким образом, изменение приоритета для LCASE_LETTER не поможет. Но не допустить, чтобы первое правило было пустым, будет.

Алгоритм Эрлибудет знать, как разрешить эту неоднозначность автоматически.

Я задавал тот же вопрос на lark-parser странице github. Ответ от там .

...