Как только непосредственные предшественники будут введены в матрицу, мы можем сделать следующие заключения. Например, из порождающих правил
P®QR
Q®qR
можно заключить, что q есть символ (не непосредственного) предшественника Р. Или же, как вытекает из матрицы непосредственных предшественников, единица в Р-й строке Q-го столбца и единица в Q-й строке q-го столбца свидетельствует о том, что, если мы хотим сформировать полную матрицу предшественников (а не только непосредственных), нам нужно поместить единицу в P-ю строку q-го столбца. В обобщенном варианте, когда в
-ой позиции и в
стоят единицы, следует поставить единицу в
-ю позицию. Пусть, однако, и в
-й позиции также стоит единица. Тогда этот процесс рекомендуется выполнить вновь, чтобы поставить единицу в
-ю позицию. Пусть, однако, и в
-ой позиции также стоит единица. Тогда этот процесс рекомендуется выполнить вновь, чтобы поставить единицу в
-ю позицию, и повторять его до тех пор, пока не будет таких случаев, когда в
-й позиции и в
-ой позиции появляются единицы, а в
-й позиции – нет.
Приведенный выше алгоритм иллюстрирует множество порождающих правил:
A®BC
B®XY
X®aa,
из которых легко вывести три единицы в матрицу непосредственных предшественников и путем дедукции еще три единицы – в полную матрицу предшествования в соответствии с тем, что X является непосредственным предшественником А, а а – непосредственным предшественником В, а также А (табл. 4.6).
Таблица 4.6.
A | B | C | … | X | Y | a | … | |
A | 1 | 1 | 1 | |||||
B | 1 | 1 | ||||||
C | ||||||||
. . . | ||||||||
X | 1 | |||||||
Y |
Этот процесс называется нахождением транзитивного замыкания, а сама матрица – матрицей достижимости. В этой матрице единицы соответствуют вершинам, между которыми есть соединительные пути.
На основании массива пустых строк матрицы можно проверить признак LL(1). Там, где в левой части более одного правила появляется нетерминал, необходимо вычислить направляющие символы различных альтернативных правых частей. Если для каких-либо из этих нетерминалов различные множества направляющих символов не являются непересекающимися, грамматика окажется не LL(1). В противном случае она будет LL(1).
Рассмотренный выше алгоритм используется в двух целях:
1) для определения правильности (принадлежности) данной грамматики к LL(1)-грамматике;
2) для преобразования произвольной грамматики к виду LL(1).
LL(1) – грамматика очень удобна для организации процесса семантического разбора.
4.2. LL(1)-таблица разбора
Найдя LL(1)-грамматику для языка, можно перейти к следующему этапу – применению найденной грамматики в фазе разбора. Обычно модуль компилятора, занимающийся семантическим разбором, называется драйвером. Драйвер указывает на то место в синтаксисе, которое соответствует текущему входному символу. Составной частью драйвера является стек, который служит для запоминания адресов возврата всякий раз, когда он входит в новое порождающее правило, соответствующее какому-нибудь нетерминалу.
Опишем сначала возможный вид таблицы разбора, а затем рассмотрим возможные способы ее оптимизации относительно используемых вычислительных ресурсов.
Таблица разбора в общем виде представляет собой одномерный массив структур вида:
declare 1 TABLE,
2 terminals list,
2 jump int,
2 accept bool,
2 stack bool,
2 return bool,
2 error bool;
где list
declare 1 list,
2 term string,
2 next pointer;
Кроме того, для работы драйвера нужен стек адресов возврата и указатель стека.
В таблице каждому шагу процесса разбора соответствует один элемент. В процессе разбора осуществляются следующие шаги.
1) Проверка предварительно просматриваемого символа, для того чтобы выяснить, не является ли он направляющим для какой-либо конкретной правой части порождающего правила. Если этот символ – не направляющий и имеется альтернативная правая часть правила, то она проверяется на следующем этапе. В особом случае, когда правая часть начинается с терминала, множество направляющих символов состоит только из одного терминала.
2) Проверка терминала, появляющегося в правой части порождающего правила.
3) Проверка нетерминала. Она заключается в проверке нахождения предварительно просматриваемого символа в одном из множеств направляющих символов для данного нетерминала, помещению в стек адреса возврата и переходу к первому правилу, относящемуся к этому нетерминалу. Если нетерминал появился в конце правой части правила, то нет необходимости помещать в стек адрес его возврата.
Таким образом, в таблицу разбора включается по одному элементу на каждое правило грамматики и на каждый экземпляр терминала или нетерминала правой части правил. Кроме того, в таблице будут находиться элементы на реализацию пустой строки в правой части правил (по одному на каждую реализацию).
Драйвер содержит процедуру, которая обрабатывает элементы таблицы разбора и определяет следующий элемент для обработки. Поле перехода обычно дает следующий элемент обработки, если значение поля возврата не окажется истиной. В последнем случае адрес следующего элемента берется из стека (что соответствует концу правила). Если же предварительно просматриваемый символ отсутствует в списке терминалов и значение поля ошибки окажется ложью, нужно обрабатывать следующий элемент таблицы с тем же предварительно просматриваемым символом (способ обращения с альтернативными правыми частями).
Рассмотрим схему построения таблицы разбора и соответствующей программы для следующей грамматики:
(1) PROGRAM ® begin DECLIST semi STATLIST end
(2) DECLIST ® d X
(3) X ® comma DECLIST
(4) X ® e
(5) STATLIST ® s Y
(6) Y ® comma STATLIST
(7) Y ® e
Сначала представим грамматику в виде схемы (рис. 4.1). В скобках и справа на рисунке указаны номера элементов таблицы разбора.
Таблица разбора, соответствующая этой грамматике может быть представлена в виде табл. 4.6.
![]() |
(1) | PROGRAM |
| begin | (2) | |||||||
DECLIST | (3) | ||||||||||
semi | (4) | ||||||||||
STATLIST | (5) | ||||||||||
end | (6) | ||||||||||
(7) | DECLIST | d | (8) | ||||||||
X | (9) | ||||||||||
(10) | X1 | comma | (12) | ||||||||
(11) | X2 | DECLIST | (13) | ||||||||
e | (14) | ||||||||||
(15) | STATLIST | s | (16) | ||||||||
Y | (17) | ||||||||||
(18) | Y1 | comma | (20) | ||||||||
(19) | Y2 | STATLIST | (21) | ||||||||
e | (22) |
Рис. 4.1. Схема грамматики
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |




