LL(k)-грамматики, множества FIRST и FOLLOW — различия между версиями
Shersh (обсуждение | вклад) (→Источники информации) |
Shersh (обсуждение | вклад) (→Теорема о связи LL(1)-грамматики с множествами FIRST и FOLLOW: добавлено доказательство) |
||
Строка 61: | Строка 61: | ||
# <tex> A \to \alpha,\ A \to \beta, A \in N,\ \varepsilon \in \mathrm{FIRST}(\alpha) \ \Rightarrow \ \mathrm{FOLLOW}(A) \cap \mathrm{FIRST}(\beta) = \varnothing</tex> | # <tex> A \to \alpha,\ A \to \beta, A \in N,\ \varepsilon \in \mathrm{FIRST}(\alpha) \ \Rightarrow \ \mathrm{FOLLOW}(A) \cap \mathrm{FIRST}(\beta) = \varnothing</tex> | ||
|proof= | |proof= | ||
− | * <tex> \ | + | <tex> \Leftarrow </tex> |
− | + | ||
− | * <tex> \Rightarrow </tex> | + | Предположим, что данная грамматика не будет LL(1)-грамматикой. Значит, у какого-то слова <tex> w </tex> существует два различных левосторонних вывода. |
− | + | * <tex> S \Rightarrow^* p A \gamma \Rightarrow p \alpha \gamma \Rightarrow^* p c \alpha' \gamma </tex> | |
+ | * <tex> S \Rightarrow^* p A \gamma \Rightarrow p \beta \gamma \Rightarrow^* p c \beta' \gamma </tex> | ||
+ | Но это противоречит тому, что <tex> \mathrm{FIRST}(\alpha) \cap \mathrm{FIRST}(\beta) = \varnothing </tex>. | ||
+ | |||
+ | Аналогично проверятся второе условие. Если, например, <tex> \alpha \Rightarrow^* \varepsilon </tex>, то <tex> \varepsilon \in \mathrm{FIRST}(\alpha) </tex>, и <tex> \mathrm{FOLLOW}(A) \cap \mathrm{FIRST}(\beta) \ne \varnothing </tex> | ||
+ | |||
+ | <tex> \Rightarrow </tex> | ||
+ | |||
+ | Предположим, что есть два различных правила <tex> A \to \alpha </tex> и <tex> A \to \beta </tex> таких, что <tex> c \in \mathrm{FIRST}(\alpha) \cap \mathrm{FIRST}(\beta) </tex>. Тогда: | ||
+ | * <tex> S \Rightarrow^* p A \gamma \Rightarrow p \alpha \gamma \Rightarrow^* p c \alpha' \gamma </tex> | ||
+ | * <tex> S \Rightarrow^* p A \gamma \Rightarrow p \beta \gamma \Rightarrow^* p c \beta' \gamma </tex> | ||
+ | Последний переход можно совершить, так как <tex> c </tex> лежит в пересечении множеств <tex> \mathrm{FIRST} </tex> двух правил вывода. Так как грамматика <tex> \Gamma </tex> является LL(1)-грамматикой, то из [[#defLLK | определения]] следует, что <tex> \alpha = \beta </tex>. Это противоречит предположению, что <tex> \alpha </tex> и <tex> \beta </tex> {{---}} различные правила. | ||
+ | |||
+ | Второе условие проверяется аналогичным образом. | ||
}} | }} | ||
=== Следствия === | === Следствия === |
Версия 16:45, 28 июня 2014
Наибольший интерес в построении синтаксических анализаторов (парсеров) представляют LL(1)-грамматики, так как для них возможно построение нисходящих парсеров без возврата, то есть без корректировки выбранных правил в грамматике. LL(1)-грамматики являются подмножеством КС-грамматик. Однако для достаточно большого количества формальных языков можно построить LL(1)-грамматику, например, для языка арифметических выражений и даже для некоторых языков программирования, в частности можно и для языка Java.
Содержание
LL(k)-грамматика
Дадим теперь формально определение LL(k)-грамматики.
Определение: |
Пусть где | — КС-грамматика. Рассмотрим два произвольных левосторонних вывода слова в этой грамматике:
LL(1)-грамматика является частным случаем. Её определение почти такое же, только вместо строки
один символ .Неформально это означает, что, посмотрев на очередной символ после уже выведенной части слова, можно однозначно определить, какое правило из грамматики выбрать.
FIRST и FOLLOW
Ключевую роль в построении парсеров для LL(1)-грамматик играю множества
и .Пусть
— символ из алфавита , — строки из нетерминалов и терминалов (возможно пустые), — нетерминалы грамматики (начальный и произвольный соответственно), — символ окончания слова. Тогда определим и следующим образом:Определение: |
Определение: |
Другими словами, достижимых из начального.
— все символы (терминалы), с которых могут начинаться всевозможные выводы из , а — всевозможные символы, которые встречаются после нетерминала во всех правилах грамматики,Примеры
Множества
и могут отличаться даже для одной грамматики, если она задана разными правилами. Рассмотрим пример двух различных грамматик для языка правильных скобочных последовательностей.Правило | FIRST | FOLLOW |
---|---|---|
A | ||
B |
Теорема о связи LL(1)-грамматики с множествами FIRST и FOLLOW
Далее будет показано, как множества
и связаны с понятием LL(1)-грамматики.Теорема: |
Доказательство: |
Предположим, что данная грамматика не будет LL(1)-грамматикой. Значит, у какого-то слова существует два различных левосторонних вывода.Но это противоречит тому, что .Аналогично проверятся второе условие. Если, например, , то , и
Предположим, что есть два различных правила и таких, что . Тогда:Последний переход можно совершить, так как определения следует, что . Это противоречит предположению, что и — различные правила. Второе условие проверяется аналогичным образом. лежит в пересечении множеств двух правил вывода. Так как грамматика является LL(1)-грамматикой, то из |
Следствия
Сформулируем несколько важных cледствий из теоремы.
Левая рекурсия
Утверждение (1): |
Грамматика cодержит левую рекурсию не является LL(1)-грамматикой. |
Если грамматика содержит левую рекурсию, значит, в ней существует какой-то нетерминал Тогда понятно, что с правилами , где — строка из терминалов и нетерминалов, не начинающаяся с . , и это противоречит первому условию теоремы. |
Чтобы избавиться от левой рекурсии, можно воспользоваться алгоритмом устранения левой рекурсии.
Левая факторизация
Утверждение (2): |
Грамматика cодержит правое ветвление не является LL(1)-грамматикой. |
Наличие в грамматике правого ветвления означает, что существует правило Очевидно, что . . Поэтому грамматика не будет LL(1)-грамматикой по первому условию теоремы. |
Алгоритм устранения правого ветвленения
Чтобы избавиться от правого ветвления, нужно воспользоваться алгоритмом левой факторизации. Его суть заключается в следующем: для каждого нетерминала
ищем самый длинный префикс, общий для двух или более правил вывода из . Важно, чтобы как можно больше строк имело общий префикс, и можно было вынести части правил после общего префикса в отдельный нетерминал. Более формально, рассмотрим правила
Причём
, а наибольший общий префикс и равен . Тогда изменим грамматику следующим образом, введя новый нетерминал :
Алгоритм завершится, когда в грамматике не будет правого ветвления. Он завершится за конечное число шагов, так как каждый раз длина правой части правил уменьшается ходя бы на единицу, а тривиальные префиксы мы не рассматриваем. К тому же, алгоритм не меняет язык грамматики, следовательно, является корректным.
Замечание: отсутствие левой рекурсии и правого ветвления в грамматике не является необходимым условием того, что она будет LL(1)-грамматикой. После их устранения грамматика всё ещё может остаться не LL(1)-грамматикой.
См. также
Источники информации
- Wikipedia — LL grammar
- LL(k)-грамматики и трансляция
- Альфред Ахо, Рави Сети, Джеффри Ульман. Компиляторы. Принципы, технологии, инструменты. Издательство Вильямс, 2003. ISBN 5-8459-0189-8