Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные работы по СПО.doc
Скачиваний:
6
Добавлен:
30.10.2018
Размер:
370.18 Кб
Скачать

Содержание отчета

  1. Исходное выражение;

  2. Результаты синтаксического разбора и свертки в виде таблицы;

  3. Возможные варианты оптимизации;

  4. Исходное выражение в виде польской записи.

Контрольные вопросы

  1. В чем достоинство табличного представления выражений?

  2. Какие виды оптимизации возможны при свертке?

  3. Зачем в таблицы лексем вводятся приоритеты операций?

  4. Возможна ли свертка выражений при движении справа налево?

  5. Чем определяется размер таблицы-результата свертки?

Лабораторная работа №7

Синтаксический разбор

Цель работы: изучение процедуры нисходящего и восходящего синтаксического разбора предложений некоторого языка.

Введение

Синтаксический анализ цепочки некоторого языка представляет собой построение на основе продукций конкретной грамматики дерева разбора[5], которое характеризуется следующими условиями:

  • каждая вершина дерева обозначается символом грамматики А  (VN  VT);

  • корень дерева – вершина, обозначенная целевым символом S;

  • листья дерева (концевые вершины) – вершины, представляющие терминальные символы или пустую цепочку ;

  • если некоторая вершина (узел) дерева представляет А  VN, а связанные с ним узлы – символами b1, b2, …, bn, (n > 0), где bi  (VN  VT  {}), , то в грамматике G для данного дерева существует правила вида

(А  b1, b2, …, bn)  Р.

Дерево вывода строится или сверху вниз, или снизу вверх.

Процедура построения дерева сверху вниз:

  1. Корень дерева – целевой символ S;

  2. Выбор подходящего правила и раскрытие символа на несколько символов первого уровня;

  3. Выбирается крайняя нетерминальная вершина ( для левостороннего вывода – левая, для правостороннего – правая) и она с помощью соответствующего правила раскрывается на несколько вершин следующего уровня:

  4. Процесс заканчивается, когда все вершины будут представлять терминальные символы грамматики.

Пример: необходимо провести синтаксический анализ следующего предложения на языке Паскаль

for sdvig := 3 to m[12] do writeln(‘*’);

Предположим, что в грамматике языка существуют следующие продукции:

P:

1: S  for <пц> := <нз> (to|downto) <кз> do <оператор>;

2: <пц>  <имя переменной>

3: <имя переменной>  <буква>{(<буква>|<цифра>|<разрешенный знак>)

4: <буква>  (a|b|c| … |Y|Z)

5: <цифра>  (0|1|2 … |9)

12: <нз>  <значение перечисляемого типа>

13: <значение перечисляемого типа>  (<константа перечисляемого типа>|<выражение перечисляемого типа>|<простая переменная перечисляемого типа>|<индексированная переменная перечисляемого типа>)

14: <выражение перечисляемого типа>  (<целочисленное выражение>|<логическое выражение>)

На основании этих правил дерево разбора приведенного выше предложения можно представить так (рис. 7.1).

Построение дерева заканчивается, когда все концевые вершины представлены терминальными символами. Если данное условие выполнить не удается, то предложение является синтаксически не корректным. При этом надо помнить, что в реальных компиляторах в качестве терминальных символов рассматриваются коды лексем.

При движении снизу вверх строительство начинается с листьев дерева в виде терминальных символов. Построение идет по слоям путем выбора подходящих правил вывода. Естественно, движение ведется слева направо при левостороннем выводе и справа налево при правостороннем выводе.

Для представленной ниже грамматики проведем оба вида вывода.

G({(,+,-,/,),*,c,b}, {S,R,T,F,E}, P, S)

P:

S  T | TR

R  +T | -T | +TR | -TR

T  E | EF

F  *E | /E | *EF | /EF

E  (S) | c | b

Рис. 7.1

Построение дерева заканчивается, когда все концевые вершины представлены терминальными символами. Если данное условие выполнить не удается, то предложение является синтаксически некорректным. При этом надо помнить, что в реальных компиляторах в качестве терминальных символов рассматриваются коды лексем.

При движении снизу вверх строительство начинается с листьев дерева в виде терминальных символов. Построение идет по слоям путем выбора подходящих правил вывода. Естественно, движение ведется слева направо при левостороннем выводе и справа налево при правостороннем выводе.

Для представленной ниже грамматики проведем оба вида вывода.

G({(,+,-,/,),*,c,b}, {S,R,T,F,E}, P, S)

P:

S  T | TR

R  +T | -T | +TR | -TR

T  E | EF

F  *E | /E | *EF | /EF

E  (S) | c | b

Предварительно продукции множества Р нумеруются, например, так:

1: S  T; S  TR

11 12

2: R  +T; R  -T; R  +TR; R  -TR

21 22 23 24

3: T  E; T  EF

31 32

4: F  *E; F  /E; F  *EF; F  /EF

41 42 43 44

5: E  (S); E  c; E  b

51 52 53

Сначала проведем левостронний разбор цепочки с + (с * b). Дерево разбора представлено на рис. 7.2. А сам вывод представлен шагами

S  TR  ER  cR  c + T  c + E  c + (S)  c + (T)  c + (EF)  c + (cF)  c + (c * E) 

c + (c * b)

Последовательность используемых продукций:

12 31 52 22 31 51 11 32 52 41 53.

Правостронний вывод предполагает движение снизу вверх, т.е. в этом случае обе полученные выше последовательности будут переписаны в обратном порядке.