Решение зависших if, elsif и else в Bison без объявлений ассоциативности
Я реализую синтаксический анализатор для языка, который имеет операторы if-elsif-else и не может сделать мою грамматику однозначной. Нашему классу компиляторов был предоставлен раздаточный материал по решению проблемы зависшего else для операторов if-else с использованием подходов соответствия / несоответствия следующим образом:
%token IF EXP ELSE XX
stmts: stmts stmt ';'
| stmt ';'
;
stmt : matched
| unmatched
;
matched: IF '(' EXP ')' matched ELSE matched
| XX
;
unmatched : IF '(' EXP ')' matched
| IF '(' EXP ')' unmatched
| IF '(' EXP ')' matched ELSE unmatched
;
Грамматическая документация, предоставляемая для нашего языка, определена так, чтобы включать выражения if - elsif- else, где:
selectionStmt → IF simpleExpression THEN statement elsifList
| IF simpleExpression THEN statement elsifList ELSE statement
elsifList → elsifList ELSIF simpleExpression THEN statement
| *empty*
где строчные слова обозначают продукцию, а прописные - терминалы.
Эти предоставленные продукты неоднозначны и должны быть решены при реализации грамматики в bison. Вот прогресс, которого я добился в реализации его в Bison:
statement: stmtMatched
| selectionStmtUnmatched
elsifList: elsifList ELSIF simpleExpression THEN statement
| %empty
stmtMatched: IF simpleExpression THEN stmtMatched elsifList ELSE
stmtMatched
| otherStatement
selectionStmtUnmatched: IF simpleExpression THEN statement elsifList
| IF simpleExpression THEN stmtMatched elsifList ELSE
selectionStmtUnmatched
otherStatement: expressionStmt
| compoundStmt
| iterationStmt
| returnStmt
| breakStmt
Есть ли предложения по изменению грамматики для соответствия продуктам elsif аналогично использованию согласованных и несогласованных операторов для решения зависшей проблемы if-else и избавления от любого сдвига / уменьшения и уменьшения / уменьшения ошибок?
Изменить 1: я добился большего прогресса в более простой версии грамматики, чтобы гарантировать, что elsifLists может следовать только согласованным операторам:
stmt: matched
| unmatched
matched: IF '(' EXP ')' THEN matched elsifList ELSE matched
| %empty
unmatched: IF '(' EXP ')' THEN matched elsifList
| IF '(' EXP ')' THEN unmatched
| IF '(' EXP ')' THEN matched elsifList ELSE unmatched
elsifList: elsifList ELSIF EXP THEN stmt
| %empty
Но у меня все еще возникают конфликты сдвига / уменьшения:
State 12
3 matched: IF '(' EXP ')' THEN matched elsifList . ELSE matched
5 unmatched: IF '(' EXP ')' THEN matched elsifList .
7 | IF '(' EXP ')' THEN matched elsifList . ELSE unmatched
8 elsifList: elsifList . ELSIF EXP THEN stmt
ELSE shift, and go to state 13
ELSIF shift, and go to state 14
ELSE [reduce using rule 5 (unmatched)]
ELSIF [reduce using rule 5 (unmatched)]
$default reduce using rule 5 (unmatched)
Изменить 2: я добился достаточного прогресса в простой грамматике, чтобы гарантировать, что операторам elsif предшествуют согласованные операторы. Итоговая грамматика:
stmt: matched
| unmatched
matched: IF '(' EXP ')' THEN matched elsifList ELSE matched
| %empty
unmatched: IF '(' EXP ')' THEN matched elsifList
| IF '(' EXP ')' THEN unmatched
| IF '(' EXP ')' THEN matched elsifList ELSE unmatched
elsifList: elsifList ELSIF EXP THEN matched
| %empty
Я обновил фактическую грамматику синтаксического анализатора для фактического языка, чтобы гарантировать, что за несогласованными операторами не может следовать elsifList, а за elsifLists могут следовать только согласованные операторы:
statement : stmtMatched |
selectionStmtUnmatched
;
otherStatement : expressionStmt
| compoundStmt
| iterationStmt
| returnStmt
| breakStmt
;
elsifList : elsifList ELSIF simpleExpression THEN stmtMatched
| %empty
;
stmtMatched : IF simpleExpression THEN stmtMatched elsifList ELSE stmtMatched
| otherStatement
;
selectionStmtUnmatched : IF simpleExpression THEN stmtMatched elsifList
| IF simpleExpression THEN selectionStmtUnmatched
| IF simpleExpression THEN stmtMatched elsifList ELSE selectionStmtUnmatched
Полученная грамматика все еще дает мне 2 конфликта сдвига / уменьшения:
State 164
44 elsifList: elsifList . ELSIF simpleExpression THEN stmtMatched
46 stmtMatched: IF simpleExpression THEN stmtMatched elsifList . ELSE stmtMatched
48 selectionStmtUnmatched: IF simpleExpression THEN stmtMatched elsifList .
50 | IF simpleExpression THEN stmtMatched elsifList . ELSE selectionStmtUnmatched
ELSIF shift, and go to state 167
ELSE shift, and go to state 168
ELSIF [reduce using rule 48 (selectionStmtUnmatched)]
ELSE [reduce using rule 48 (selectionStmtUnmatched)]
$default reduce using rule 48 (selectionStmtUnmatched)
1 ответ
Грамматика в вашем раздаточном материале не допускает несогласованного утверждения перед else
. Это почему?
Это потому, что else
должен связываться с ближайшим, еще не сопоставленным if
. Вы можете попробовать сделать несколько деревьев синтаксического анализа вручную, чтобы понять, как это работает. Существенный момент состоит в том, что внутри несогласованного утверждения есть непревзойденноеif
который else
следует привязать к. Таким образом, двусмысленность может быть устранена, если исключить возможность пропустить непревзойденныйif
.
Что изменится, когда мы добавим elsif
? Немного. Обеelsif
а также else
должен связываться с ближайшим, еще не сопоставленным if
или elsif
. И способ гарантировать это точно такой же, как и в простом случае. Нам нужно убедиться, что заявление передelsif
совпадает.
Но ваша грамматика требует только, чтобы утверждение перед первым elsif
быть сопоставленным. Так что остаются неясности.
Подсказка: исправить очень просто. Вам просто нужно сделать группировку по-другому.