Я пытаюсь написать небольшой парсер с Ирония . К сожалению, я получаю «сдвиг-уменьшение конфликта». Грамматика не моя сильная сторона, и мне нужно сделать только одну маленькую вещь. Вот сокращенная грамматика, которая выдает ошибку:
ExpressionTerm := "asd"
LogicalExpression :=
ExpressionTerm |
LogicalExpression "AND" LogicalExpression |
LogicalExpression "OR" LogicalExpression
Что означает «конфликт сдвига-уменьшения» и как я могу его решить? Я понимаю, что это означает, что моя грамматика неоднозначна, но я не могу достаточно перевернуть свою логику, чтобы понять, как это сделать.
Добавлено: Для пояснения - "asd" - это просто буквальная строка "asd". Поэтому я ожидаю, что по этой грамматике будут проанализированы следующие выражения:
asd
asd AND asd
asd AND asd OR asd
asd OR asd AND asd OR asd
Добавлено 2: Забыл сказать, корень грамматики - LogicalExpression
.
Добавлено 3: Ах, я понял! Неоднозначность заключается в том, что выражение типа
asd AND asd OR asd
можно интерпретировать двумя различными способами:
(asd AND asd) OR asd
asd AND (asd OR asd)
Но как я могу решить это? Хорошо, я могу поставить один из И или ИЛИ, чтобы он был сильнее другого (я все равно намеревался). Но теперь я вижу, что ошибка появляется, даже если есть только один оператор. Другими словами, это также вызывает ту же ошибку:
LogicalExpression := "asd" | LogicalExpression "OR" LogicalExpression
В этом случае я хочу это:
asd OR asd OR asd
будет проанализирован на это:
(asd OR asd) OR asd
Что такое недвусмысленный способ сделать это?
Добавлено 4: Понятно!
LogicalExpression1 := LogicalExpression1 "OR" LogicalExpression2 | LogicalExpression2
LogicalExpression2 := LogicalExpression2 "AND" LogicalExpression3 | LogicalExpression3
LogicalExpression3 := "NOT" LogicalExpression4 | LogicalExpression4
LogicalExpression4 := "asd" | "(" LogicalExpression1 ")"
При этом анализируются все логические выражения с приоритетом оператора NOT-> AND-> OR. «asd» можно заменить на выражение, предназначенное для ваших терминов.