Вы можете сделать это, просто запретив форму в скобках на верхнем уровне. Это требует написания иерархии приоритетов другим способом, чтобы распространить ограничение по иерархии. Далее суффикс r
указывает на то, что производство «ограничено» и не является скобкой.
Я также исправил конфликты уменьшения / уменьшения, исключив одно из производств NOT
. См. Ниже.
(Надеюсь, я правильно понял BNF C. Я написал это в бизоне и впоследствии попытался преобразовать синтаксис.)
_ . S ::= L0r ;
IFF . L0r ::= L0 "<=>" L1 ;
IF . L0r ::= L0 "=>" L1 ;
AND . L1r ::= L1 "&" L2 ;
OR . L1r ::= L1 "|" L2 ;
NOT . L2r ::= "-" L2 ;
ID . L2r ::= Ident ;
PAREN . L3 ::= "(" L0 ")" ;
_ . L0r ::= L1r ;
_ . L1r ::= L2r ;
_ . L0 ::= L0r ;
_ . L1 ::= L1r ;
_ . L2 ::= L2r ;
_ . L0 ::= L3 ;
_ . L1 ::= L3 ;
_ . L2 ::= L3 ;
( Редактировать : я изменил правила IFF
, IF
, AND
и OR
, удалив ограничение (r
) из первых аргументов. Это позволяет правилам сопоставлять выражения, начинающиеся с круглых скобок, без сопоставления синтаксис PAREN
.)
Если вы также хотите запретить избыточные внутренние скобки (например, ((a & b))
), вы можете изменить правило PAREN
на
PAREN . L3 ::= "(" L0r ")" ;
, что приведет к L0
правило не нужно.
Вариант, который использует меньшее количество единиц продукции, можно найти в ответе от @ IraBaxter до Грамматика для выражений, которая запрещает внешние скобки .
Примечание:
Эта грамматика также приводит к примерно 6 конфликтам уменьшения / уменьшения, но разве они не являются неизбежными в рекурсивных определениях?
Нет, рекурсивные грамматики могут и должны быть однозначным. Сокращение / уменьшение конфликтов не являются неизбежными и почти всегда указывают на проблемы в грамматике. В этом случае они являются результатом избыточных производств для унарного оператора NOT. Наличие двух разных нетерминалов, которые оба могут принять "-" L3
, очевидно, приведет к неоднозначности, а неоднозначности всегда приводят к конфликтам синтаксического анализа.