- •Основы конструирования компиляторов
- •Введение. Трансляция арифметических выражений. Метод Рутисхаузера
- •1Основные понятия и определения
- •1.1Классификация компилирующих программ
- •1.2Синтаксис и семантика. Структура компилятора
- •2Формальные грамматики и их использование при лексическом и синтаксическом анализе
- •2.1Формальная грамматика и формальный язык
- •2.2Понятие грамматического разбора
- •2.3Расширенная классификация грамматик Хомского
- •2.4Распознавание регулярных грамматик
- •2.4.1Конечный автомат и его программная реализация
- •2.4.2Построение лексических анализаторов
- •2.4.3Построение синтаксических анализаторов
- •2.5Распознавание кс-грамматик
- •2.5.1Автомат с магазинной памятью
- •2.5.2Синтаксические анализаторы ll(k)-грамматик. Метод рекурсивного спуска
- •2.5.3Синтаксические анализаторы lr(k)-грамматик. Грамматики предшествования
- •2.6Польская запись. Алгоритм Бауэра-Замельзона
- •3Распределение памяти
- •4Генерация и оптимизация кодов
- •1 Основные понятия и определения 3
- •2 Формальные грамматики и их использование при лексическом и синтаксическом анализе 5
- •3 Распределение памяти 27
- •4 Генерация и оптимизация кодов 28
2.4.3Построение синтаксических анализаторов
Синтаксические анализаторы регулярных языков на вход получают строку лексем.
Пример. Синтаксический анализатор списка описания целых скаляров, массивов и функций (упрощенный вариант), например: int xaf, y22[5], zrr[2][4], re[N], fun(), *g;
После лексического анализа входная строка представлена в алфавите:
V – идентификатор; N – целочисленная константа; служебные символы: «[ ] ( ) , ; *».
Функцию переходов зададим синтаксической диаграммой (см. рисунок 7).
Рисунок 7 – Синтаксическая диаграмма
По диаграмме построим таблицу автомата (см. таблицу 7).
Таблица 7 –Таблица переходов
|
V |
N |
* |
( |
) |
[ |
] |
, |
; |
Другие |
1 |
3 |
E |
2 |
E |
E |
E |
E |
E |
E |
E |
2 |
3 |
E |
E |
E |
E |
E |
E |
E |
E |
E |
3 |
E |
E |
E |
4 |
E |
6 |
E |
1 |
К |
E |
4 |
E |
E |
E |
E |
5 |
E |
E |
E |
E |
E |
5 |
E |
E |
E |
E |
E |
E |
E |
1 |
К |
E |
6 |
E |
7 |
E |
E |
E |
E |
E |
E |
E |
E |
7 |
E |
E |
E |
E |
E |
E |
8 |
E |
E |
E |
8 |
E |
E |
E |
E |
E |
6 |
E |
1 |
К |
E |
Алгоритм распознавателя:
Ind := 1
q := 1
Цикл-пока q «Е» и q «К»
q := Table [q, Pos(S[Ind], «VN*()[];»)]
Ind := Ind +1
Все-цикл
Если q = «К»
то Выполнить А3
Вывести сообщение «Это число»
иначе Вывести сообщение Дi
Все-если
2.5Распознавание кс-грамматик
2.5.1Автомат с магазинной памятью
Распознавание КС-грамматик выполняется автоматом с магазинной памятью. Автомат с магазинной памятью определяется семеркой:
PM = (Q, , Г, , q0, z0, F),
где Q – конечное множество состояний автомата;
– конечный входной алфавит;
Г – конечное множество магазинных символов;
(q, ck, zj) – функция переходов;
q0 Q – начальное состояние автомата;
z0 Г – символ, находящийся в магазине в начальный момент,
F Q – множество заключительных (допускающих) состояний.
Пример. Синтаксический анализатор выражений.
Алфавит языка записи выражений: = {<Ид>, +, –, *, /, (, ), ◄, ►}. Грамматика описывается синтаксическими диаграммами, представленными на рисунке 8.
Рисунок 8 – Синтаксические диаграммы
Подставляем диаграммы одна в другую, исключая промежуточные нетерминалы Терм и Множитель. В результате получаем полную синтаксическую диаграмму (см. рисунок 9), которая состоит из двух частей: основной и рекурсивной, что связано с наличием рекурсивного вложения правил продукции.
Рисунок 9 – Синтаксическая диаграмма
По диаграмме строим таблицу автомата, которая также будет состоять из двух частей (см. таблицу 8), которые можно объединить в одну.
Таблица 8 – Таблица переходов автомата
|
<Ид> |
+ |
- |
* |
/ |
( |
) |
► |
◄ |
1 |
|
|
|
|
|
|
|
2 |
|
2 |
S=3 |
|
|
|
|
S =3 |
|
|
|
3 |
|
|
|
|
|
|
|
|
К |
|
<Ид> |
+ |
- |
* |
/ |
( |
) |
► |
◄ |
X |
4 |
|
|
|
|
5 |
|
|
|
4 |
|
11 |
11 |
7 |
7 |
|
S |
|
S |
5 |
S =6 |
|
|
|
|
S =6 |
|
|
|
6 |
|
|
|
|
|
|
4 |
|
|
7 |
8 |
|
|
|
|
9 |
|
|
|
8 |
|
11 |
11 |
|
|
|
S |
|
S |
9 |
S =10 |
|
|
|
|
S =10 |
|
|
|
10 |
|
|
|
|
|
|
8 |
|
|
11 |
S =Y |
|
|
|
|
S =Y |
|
|
|
Y |
|
|
|
|
|
|
S |
|
S |
Условные обозначения:
К – конец разбора, E – состояние ошибки (все пустые ячейки должны содержать E),
Y = <состояние> – рекурсивный вызов распознавателя, справа указан номер состояния после возврата из данного вызова;
Y – возврат из рекурсии, следующее состояние определяется значением Y,
При разработке алгоритма используем следующие обозначения:
Mag – стек (магазин) распознающего автомата, элементы, записываемые в стек, – терминальные и нетерминальные символы; – запись в стек, – чтение из стека;
q – текущее состояние;
Table (<Текущее состояние>, <Анализируемый символ>) – элемент таблицы (матрицы) переходов, состоящий из следующих полей: q – следующее состояние (в том числе «» – рекурсивный вызов, «» – возврат из рекурсии), S – состояние после возврата из рекурсии, если необходим рекурсивный вызов, или ;
String – исходная строка;
Ind – номер символа исходной строки.
Алгоритм программы, реализующей автомат, будет выглядеть следующим образом:
q:=1
Ind := 1
Mag :=
Цикл-пока q «E» и q «К»
q := Table [q, String[Ind]].q
Если q =
то Mag Table [q, String[Ind]].S
q := X
иначе Если q =
то Mag q
иначе Ind := Ind +1
Все-если
Все-если
Если q = «К»
то «Строка принята»
иначе «Строка отвергнута»
Все-если
Однако построение такого автомата для сложного языка – задача не простая. Поэтому в литературе предлагаются другие способы. Обычно выделяют подклассы грамматик, обладающих определенными свойствами, основываясь на которых можно строить конкретные распознаватели.
