Алгоритм Эрли позволяет определить, выводится ли данное слово [math]w[/math] в данной контекстно-свободной грамматике [math]G[/math].
Вход: КС грамматика [math] G=\langle N,\Sigma, P, S \rangle[/math] и слово [math]w[/math].
Выход: [math]true[/math], если [math]w[/math] выводится в [math]G[/math]; [math]false[/math] — иначе.
Чтобы воспользоваться леммой, необходимо найти [math]D_n[/math] для [math]w[/math]. Алгоритм Эрли является динамическим алгоритмом: он последовательно строит список разбора, причём при построении [math]D_j[/math] используются [math]D_0, \ldots, D_{j}[/math] (то есть элементы списков с меньшими номерами и ситуации, содержащиеся в текущем списке на данный момент).
Алгоритм основывается на следующих трёх правилах:
- Если [math][A \rightarrow \alpha \cdot w_{j} \beta, i] \in D_{j-1}[/math] (где [math]w_j[/math] — [math]j[/math]-ый символ строки), то [math][A \rightarrow \alpha w_{j} \cdot \beta, i] \in D_j[/math].
- Если [math][B \rightarrow \eta \cdot, i] \in D_j[/math] и [math][A \rightarrow \alpha \cdot B \beta, k] \in D_i[/math], то [math][A \rightarrow \alpha B \cdot \beta, k] \in D_j[/math].
- Если [math][A \rightarrow \alpha \cdot B \beta, i] \in D_{j} [/math] и [math](B \rightarrow \eta) \in P [/math], то [math][B \rightarrow \cdot \eta, j] \in D_{j}[/math].
Псевдокод
Для простоты добавим новый стартовый вспомогательный нетерминал [math]S'[/math] и правило [math](S' \rightarrow S)[/math].
function [math]\mathtt{earley}(G, w)[/math]:
// Инициализация
[math] D_{0} = \lbrace [S' \rightarrow \cdot S, 0] \rbrace [/math]
for i = 1 to len(w) - 1
[math]D_i[/math] = [math]\varnothing [/math]
// Вычисление ситуаций
for j = 0 to len(w) - 1
[math]\mathtt{scan}(D, j, G, w)[/math]
while [math]D_j[/math] изменяется
[math]\mathtt{complete}(D, j, G, w)[/math]
[math]\mathtt{predict}(D, j, G, w)[/math]
// Результат
if [math][S' \rightarrow S \cdot, 0] \in D_{len(w)} [/math]
return True
else
return False
// Первое правило
function [math]\mathtt{scan}(D, j, G, w)[/math]:
if [math]j[/math] == [math]0[/math]
return
for [math][A \rightarrow \alpha \cdot a \beta, i] \in D_{j - 1} [/math]
if [math]a[/math] == [math]w_{j - 1}[/math]
[math]D_{j}[/math] [math] \cup[/math]= [math][A \rightarrow \alpha \cdot a \beta, i][/math]
// Второе правило
function [math]\mathtt{complete}(D, j, G, w)[/math]:
for [math][B \rightarrow \eta \cdot, i] \in D_{j} [/math]
for [math][A \rightarrow \alpha \cdot B \beta, k] \in D_{i} [/math]
[math]D_{j}[/math] [math] \cup[/math]= [math][A \rightarrow \alpha B \cdot \beta, k][/math]
// Третье правило
function [math]\mathtt{predict}(D, j, G, w)[/math]:
for [math][A \rightarrow \alpha \cdot B \beta, i] \in D_{j} [/math]
for [math](B \rightarrow \eta) \in P [/math]
[math]D_{j}[/math] [math]\cup[/math]= [math][B \rightarrow \cdot \eta, j][/math]
Построим список разбора для строки [math]w = (a + a)[/math] в грамматике со следующими правилами:
- [math]S \rightarrow T + S[/math];
- [math]S \rightarrow T [/math];
- [math]T \rightarrow F * T[/math];
- [math]T \rightarrow F[/math];
- [math]F \rightarrow ( S )[/math];
- [math]F \rightarrow a[/math].
[math]I_0[/math]
|
Ситуация |
Из правила
|
[math][S' \rightarrow \cdot S, 0][/math] |
0
|
[math][S \rightarrow \cdot T + S, 0][/math] |
3
|
[math][S \rightarrow \cdot T, 0][/math] |
3
|
[math][T \rightarrow \cdot F * T, 0][/math] |
3
|
[math][T \rightarrow \cdot F, 0][/math] |
3
|
[math][F \rightarrow \cdot ( S ), 0][/math] |
3
|
[math][F \rightarrow \cdot a, 0][/math] |
3
|
|
|
[math]I_1[/math]
|
Ситуация |
Из правила
|
[math][F \rightarrow ( \cdot S ), 0][/math] |
1
|
[math][S \rightarrow \cdot T + S, 1][/math] |
3
|
[math][S \rightarrow \cdot T, 1][/math] |
3
|
[math][T \rightarrow \cdot F * T, 1][/math] |
3
|
[math][T \rightarrow \cdot F, 1][/math] |
3
|
[math][F \rightarrow \cdot ( S ), 1][/math] |
3
|
[math][F \rightarrow \cdot a, 1][/math] |
3
|
|
|
[math]I_2[/math]
|
Ситуация |
Из правила
|
[math][F \rightarrow a \cdot, 1][/math] |
1
|
[math][T \rightarrow F \cdot * T, 1][/math] |
2
|
[math][T \rightarrow F \cdot , 1][/math] |
2
|
[math][S \rightarrow T \cdot , 1][/math] |
2
|
[math][S \rightarrow T \cdot + S, 1][/math] |
2
|
[math][F \rightarrow ( S \cdot ), 0][/math] |
2
|
|
|
[math]I_3[/math]
|
Ситуация |
Из правила
|
[math][S \rightarrow T + \cdot S, 1][/math] |
1
|
[math][S \rightarrow \cdot T + S, 3][/math] |
3
|
[math][S \rightarrow \cdot T, 3][/math] |
3
|
[math][T \rightarrow \cdot F * T, 3][/math] |
3
|
[math][T \rightarrow \cdot F, 3][/math] |
3
|
[math][F \rightarrow \cdot ( S ), 3][/math] |
3
|
[math][F \rightarrow \cdot a, 3][/math] |
3
|
|
|
[math]I_4[/math]
|
Ситуация |
Из правила
|
[math][F \rightarrow a \cdot , 3][/math] |
1
|
[math][T \rightarrow F \cdot * T, 3][/math] |
2
|
[math][T \rightarrow F \cdot , 3][/math] |
2
|
[math][S \rightarrow T \cdot + S, 3][/math] |
2
|
[math][S \rightarrow T \cdot , 3][/math] |
2
|
[math][S \rightarrow T + S \cdot , 1][/math] |
2
|
[math][F \rightarrow ( S \cdot ), 0][/math] |
2
|
|
|
[math]I_5[/math]
|
Ситуация |
Из правила
|
[math][F \rightarrow ( S )\cdot , 0][/math] |
1
|
[math][T \rightarrow F \cdot * T, 0][/math] |
2
|
[math][T \rightarrow F \cdot , 0][/math] |
2
|
[math][S \rightarrow T \cdot + S, 0][/math] |
2
|
[math][S \rightarrow T \cdot , 0][/math] |
2
|
[math][S' \rightarrow S \cdot , 0][/math] |
2
|
|
|
Так как [math][S' \rightarrow S \cdot , 0] \in I_5[/math], то [math]w \in L(G) [/math].