
Алгоритм Кока-Янгера-Касами.
Обсуждаемый алгоритм предназначен для разбора методом «снизу-вверх» слов любой контекстно-свободной грамматики, т.е. это – универсальный метод. Для его применения грамматика должна быть преобразована к нормальной форме Хомского (т.е. правила имеют вид: Aa или ABC). Этот алгоритм имеет сложность O(n3) по времени и O(n2) по памяти. На первом этапе алгоритм строит треугольную таблицу с элементами tik, в каждую клетку которой помещается множество нетерминалов, из которых можно вывести отрезок слова начинающийся с символа ai и длиной k.
Формально:
tik
= {A | Aai…ai+k-1}.
Очевидно,
что множества tik
формально (рекурсивно) можно определить
так:
ti1 = {A | Aai - правило грамматики},
tij = {A | ABC - правило грамматики и k, 1k<j такое, что Btik Cti+k,j-k}.
Если в t1n есть S, то слово языку.
t16 |
|
|
|
|
|
t15 |
t25 |
|
|
|
|
t14 |
t24 |
t34 |
|
|
|
t13 |
t23 |
t33 |
t43 |
|
|
t12 |
t22 |
t32 |
t42 |
t52 |
|
t11 |
t21 |
t31 |
t41 |
t51 |
t61 |
a1 |
a2 |
a3 |
a4 |
a5 |
a6 |
Пусть заполнены все строки таблицы до j-1 включительно. Рассмотрим tij.
Эта ячейка соответствует фрагменту слова <ai…ai+j-1>. Разбиваем этот фрагмент на пары слов всеми способами. Каждому варианту разбиения соответствует пара клеток таблицы, в которых стоят нетерминалы, из которых могут быть выведены соответствующие строки. Пусть это пара (t,t). В tij поместим нетерминал A, если есть правило ABC и Bt, Ct.
Пример. Рассмотрим неоднозначную грамматику: G = ({S,L,R}, {(,)}, {SSS | LR, L(, R)}, S). Пусть задано слово ()()(). Построим таблицу.
S16 |
|
|
|
|
|
|
|
|
|
|
|
S14 |
|
S34 |
|
|
|
|
|
|
|
|
|
S12 |
|
S32 |
|
S52 |
|
L11 |
R21 |
L31 |
R41 |
L51 |
R61 |
( |
) |
( |
) |
( |
) |
На втором этапе восстанавливаем дерево вывода.
Это можно выполнить с помощью следующей рекурсивной процедуры:
GEN(i,j,A)
| 1. Если j=1 Aai – правило с номером m, то выдать m.
| 2. Если j>1. Пусть k – наименьшее из чисел, для которых Btik Cti+k,j-k и ABCR
| имеет номер m. Выбрать это правило, выдать m и выполнить последовательно:
| GEN(i,k,B) ???
GEN(i+k,j-k,C) ???
Старт: GEN(1,n,S)
Замечание. Описанный алгоритм существенно опирается на то, что грамматика имеет форму Хомского.