55
первичная фраза (иными словами, значением переменной является последняя
разобранная синтаксическая категория).
Структура стека несколько отличается от предыдущих: элементами
стека являются не отдельные символы, а цепочки символов – головы правых
частей правил. Например, последовательность
# IF <выр> THEN IF <выр> THEN <перем> :=
в стеке будет представлена следующим образом:
<перем> :=
IF <выр> THEN
IF <выр> THEN
#
Итак, в стеке хранятся те последовательности символов, которые должны
редуцироваться одновременно.
Распознаватель работает следующим образом. На каждом шаге работы
верхний элемент стека соответствует некоторой строке матрицы. По
входному терминальному символу (это – столбец) определяется элемент
матрицы, являющийся номером подпрограммы, которую нужно выполнить.
Эта подпрограмма произведет необходимую редукцию или занесет R в стек и
будет сканировать следующий исходный символ. При написании
подпрограмм будем считать, что функция PUSH(R) помещает в стек символ
R, функция SCAN() помещает очередной символ из входной цепочки в R, а
функция POP() просто извлекает из стека верхний символ (предполагается,
что он нам уже не нужен).
Схема рассуждений при формировании подпрограмм выглядит так
(рассмотрим, для примера, подпрограмму 9): сначала мы выписываем
содержимое верхнего элемента стека (для нашей подпрограммы это будет IF).
Далее записываем значение считанного терминала (это THEN) и смотрим, что
может находиться между ними (т.е. какая синтаксическая категория U):
…IF U THEN…
Судя по всему, U должно быть равно <выр>. Значит, первая процедура
нашей подпрограммы – это проверка вида
if U
<выр> then error()
Затем смотрим, не получилось ли у нас разобранной синтаксической
категории. Ничего путного пока у нас не вышло, поэтому присвоим
переменной U пустое значение (U := ''), а в стек занесем полученную голову
правила (PUSH('IF <выр> THEN')). Далее надо будет считать следующий
входной символ. Итак, подпрограмма номер 9 будет выглядеть так:
9: IF U
'<выр>' AND U
'<перем>' THEN ERROR();
PUSH('IF <выр> THEN')