Эта статья находится в разработке!
Наибольший интерес в построении синтаксических анализаторов (парсеров) представляют LL(1)-грамматики, так как для них возможно построение нисходящих парсеров без возврата, то есть без корректировки выбранных правил в грамматике. LL(1)-грамматики являются подмножеством КС-грамматик. Однако для достаточно большого количества формальных языков можно построить LL(1)-грамматику, например, для языка арифметических выражений и даже для некоторых языков программирования, в частности можно и для языка Java.
LL(k)-грамматика
Дадим теперь формально определение LL(k)-грамматики.
Определение: |
Пусть [math]\Gamma =\langle \Sigma, N, S, P \rangle[/math] — КС-грамматика. Рассмотрим два произвольных левосторонних вывода слова [math] w [/math] в этой грамматике:
- [math] S \Rightarrow^* p A \beta \Rightarrow p \alpha \beta \Rightarrow^* p y \eta [/math]
- [math] S \Rightarrow^* p A \beta \Rightarrow p \alpha' \beta \Rightarrow^* p y \xi [/math]
где [math] p [/math] и [math] y [/math] — цепочки из терминалов, уже разобранная часть слова [math] w [/math], [math] A [/math] — нетерминал грамматики, в которой есть правила [math] A \rightarrow \alpha [/math] и [math] A \rightarrow \alpha' [/math], причём [math] \alpha, \alpha', \beta, \eta, \xi [/math] — последовательности из терминалов и нетерминалов.
Тогда если при выполнении условий, что [math] |y| = k [/math] или [math] |y| \lt k, \eta = \xi = \varepsilon [/math], верно, что [math] \alpha = \alpha' [/math], то [math] \Gamma [/math] называется LL(k)-грамматикой. |
LL(1)-грамматика является частным случаем. Её определение почти такое же, только вместо строки [math] y [/math] один символ [math] c \in \Sigma \cup \{\varepsilon\} [/math].
Неформально это означает, что, посмотрев на очередной символ после уже выведенной части слова, можно однозначно определить, какое правило из грамматики выбрать.
FIRST и FOLLOW
Ключевую роль в построении парсеров для LL(1)-грамматик играю множества [math] \mathrm{FIRST} [/math] и [math] \mathrm{FOLLOW} [/math].
Пусть [math] c [/math] — символ из алфавита [math] \Sigma [/math], [math] \alpha,\ \beta [/math] — строки из нетерминалов и терминалов (возможно пустые), [math] S,\ A [/math] — нетерминалы грамматики (начальный и произвольный соответственно), [math] \$ [/math] — символ окончания слова. Тогда определим [math] \mathrm{FIRST} [/math] и [math] \mathrm{FOLLOW} [/math] следующим образом:
Определение: |
[math] \mathrm{FIRST}(\alpha) = \{c \mid \alpha \Rightarrow^* c \beta \} \cup \{ \varepsilon\ \mathrm{if}\ \alpha \Rightarrow^* \varepsilon \} [/math] |
Определение: |
[math] \mathrm{FOLLOW}(A) = \{c \mid S \Rightarrow^* \alpha A c \beta \} \cup \{ \$ \ \mathrm{if}\ S \Rightarrow^* \alpha A \} [/math] |
Другими словами, [math] \mathrm{FIRST}(\alpha) [/math] — все символы (терминалы), с которых могут начинаться всевозможные выводы из [math] \alpha [/math], а [math] \mathrm{FOLLOW}(A) [/math] — всевозможные символы, которые встречаются после нетерминала [math] A [/math] во всех правилах грамматики, достижимых из начального.
Примеры
Множества [math] \mathrm{FIRST} [/math] и [math] \mathrm{FOLLOW} [/math] могут отличаться даже для одной грамматики, если она задана разными правилами. Рассмотрим пример двух различных грамматик для языка правильных скобочных последовательностей.
- [math] A \rightarrow (A)A \mid \varepsilon [/math]
- [math] B \rightarrow BB \mid (B) \mid \varepsilon [/math]
Правило
|
FIRST
|
FOLLOW
|
A
|
[math]\{\ (,\ \varepsilon\ \} [/math]
|
[math]\{\ ),\ \$\ \} [/math]
|
B
|
[math]\{\ (,\ \varepsilon\ \} [/math]
|
[math]\{\ (,\ ),\ \$\ \} [/math]
|
Теорема о связи LL(1)-грамматики с множествами FIRST и FOLLOW
Далее будет показано, как множества [math] \mathrm{FIRST} [/math] и [math] \mathrm{FOLLOW} [/math] связаны с понятием LL(1)-грамматики.
Теорема: |
[math]\Gamma =\langle \Sigma, N, S, P \rangle[/math] — LL(1)-грамматика [math] \Leftrightarrow [/math]
- [math] A \rightarrow \alpha,\ A \rightarrow \beta, A \in N \ \Rightarrow \ \mathrm{FIRST}(\alpha) \cap \mathrm{FIRST}(\beta) = \varnothing[/math]
- [math] A \rightarrow \alpha,\ A \rightarrow \beta, A \in N,\ \varepsilon \in \mathrm{FIRST}(\alpha) \ \Rightarrow \ \mathrm{FOLLOW}(A) \cap \mathrm{FIRST}(\beta) = \varnothing[/math]
|
Доказательство: |
[math]\triangleright[/math] |
- [math] \Leftarrow [/math]
очевидно
- [math] \Rightarrow [/math]
почти очевидно |
[math]\triangleleft[/math] |
Следствия
См. также
Источники информации