Обязателен ли алгоритм GLR при разборе грамматики бизонов C? - PullRequest
0 голосов
/ 19 января 2020

Я пытаюсь изучить грамматику C с помощью flex / bison.

Я обнаружил, что зубр не может разобрать эту грамматику бизонов: https://www.lysator.liu.se/c/ANSI-C-grammar-y.html, потому что LALR алгоритм не может обрабатывать рекурсивно несколько выражений.

Обязателен ли алгоритм GLR для C грамматики?

1 Ответ

4 голосов
/ 19 января 2020

В этой грамматике нет ничего плохого, кроме:

  • она представляет собой очень старую версию C
  • , для нее требуется лексический анализатор, который может каким-то образом различать guish между IDENTIFIER и TYPE_NAME
  • он даже не пытается обработать фазы препроцессора

Кроме того, он имеет один конфликт сдвига / уменьшения в результате "болтаться" двусмысленность. Однако этот конфликт может быть проигнорирован, потому что алгоритм разрешения конфликтов Bison дает правильный результат в этом случае. (Вы можете подавить предупреждение либо с помощью директивы %expect, либо с помощью объявления приоритета, которое способствует смещению else по сравнению с уменьшением if. Или вы можете устранить неоднозначность в грамматике, используя описанную технику . на странице Википедии, ссылки на которую приведены выше. (Примечание: я не говорю о коде копирования и вставки со страницы Википедии. В случае C вам необходимо рассмотреть все случаи составных операторов, которые заканчиваются на if Statement.)

Более того, синтаксический анализатор LR не является рекурсивным, и у него нет проблем, которые можно было бы описать как сбой в «обработке рекурсивных множественных выражений». (У вас может быть такая проблема с анализатором рекурсивного спуска , хотя обойти эту проблему довольно легко.)

Таким образом, любые проблемы, с которыми вы могли столкнуться (если ваш вопрос относится к конкретной проблеме), не имеют ничего общего с тем, что описано в вашем вопросе.

Из перечисленных выше проблем больше всего беспокоит syntacti c Неоднозначность приведенного оператора. Оператор приведения не является на самом деле неоднозначным; ясно, что C компиляторам удается корректно компилировать такие выражения. Но для различения двух возможных синтаксических разборов, например, (x)-y*z, необходимо знать, называет ли x тип или переменную.

В C все имена имеют лексическую область, поэтому, безусловно, это возможно разрешить x во время компиляции. Но резолюция не является контекстно-свободной. Поскольку GLR также является техникой парсинга контекстно-свободных грамматик, использование синтаксического анализатора GLR не поможет вам напрямую. Это может быть полезно в том смысле, что синтаксические анализаторы GLR могут теоретически создавать «леса разбора», а не деревья разбора; то есть выходные данные синтаксического анализатора GLR могут эффективно содержать все возможные правильные синтаксические разборы, оставляя возможность устранить неоднозначность путем создания таблиц символов для каждой области, а затем выбирать между альтернативными синтаксическими анализами, исследуя действующую привязку имени на каждом сайте. (Это работает, потому что объявления псевдонимов типов - "typedefs" - не являются неоднозначными, поэтому все потенциальные синтаксические разборы будут иметь одинаковые объявления псевдонимов.)

Обычное решение, однако, состоит в том, чтобы проанализировать текст программы, используя детерминированный синтаксический анализатор c, поддерживающий таблицу символов во время синтаксического анализа и предоставляющий лексическому анализатору доступ к этой таблице символов, чтобы она могла различать guish между IDENTIFIER и TYPE_NAME, как того требует грамматика Вы ссылку. Эту технику вежливо называют «лексической обратной связью», хотя ее также часто называют «хакером лексера».

...