Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СПО Билеты.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
5.24 Mб
Скачать

Требования к грамматике нисходящего метода

Основным требованием является отсутствие прямой или общей левосторонней рекурсии.

Прямая рекурсия-это когда существует правило: U::=UX...

Общая левосторонняя рекурсия-это когда существуют правила: U::=VX... , V::=UY... и U=>+U

Избавиться от общей левосторонней рекурсии достаточно сложно, однако существуют методы ее обнаружения. Эта задача решается путем введения специальных отношений FIRST и FIRST+.

Отношение FIRST задается следующим образом

1 U FIRST S, если существует правило U::=S...

2 U FIRST+ S, если существует непустая последовательность правил U::=S1... ; S1::=S2... ; ... Sn::=S , т.е. существует U=>+S...;

Используя это отношение, можно утверждать, что символ U обладает общей левой рекурсией, когда возможно отношение: U FIRST + U.

Пример.

A::= Af

A::= B

B::= Ddc

B::= De

C::= e

D::= Bf

Отношения FIRST+ будет иметь следующий вид: FIRST+={(A,A), (A,B),(A,D), (B,D),(B,B), (D,B), (D,D)}.

Отсюда следует, что общая левая рекурсия имеется для символов A,B,D. Одним из формальных способов избавления от прямой левосторонней рекурсии является итерация.

Семантические программы. Перевод инфиксной записи в польскую.

В результате синтаксических и лексических разборов – производится некоторое неэквивалентное преобразование текста в другую форму.

Семантические программы осуществляют перевод исходного текста на объектный язык таким образом, что смысл исходной и объектной программы полностью совпадает. Семантическая обработка может быть совмещена с синтаксическим анализом (в момент когда определяется основа).

Для восходящего метода разбора семантический распознаватель всякий раз, когда найдена основа, и её можно привести к нетерминальному символу U, вызывает программу, связанную с правилом U::=x, где х - найденная основа.

Эта программа осуществляет семантическую обработку всех символов цепочки х и формирует ту часть символов польской записи, которая имеет непосредственное отношение к основе х. При этом выполняются 2 условия:

1) основа приводится к нетерминалу при каждой редукции

2) Если в основе встречается некоторый нетерминал V, то часть польской записи, включающая подцепочку, которая приводится к V, уже была сгенерирована.

Предположим, что генерируемая польская запись хранится в одномерном массиве Р. Целочисленная переменная J (начальное значение равно единице) содержит индекс, который указывает на первый свободный элемент массива Р. Каждый элемент массива может содержать один символ: идентификатор или оператор.

Пусть вызванная семантическая программа имеет доступ к символам основы S[1],S[2],...,S[i]. Находящемся в синтаксическом стеке S, который используется распознавателем.

Рассмотрим программу, связанную с правилом Е1::=Е2.

Если данная семантическая программа вызвана, то польская запись для Е2 и Т уже получена, т. е. массив P уже содержит

P…<код для Е2><код для Т>.

Кроме того символ, который находится правее Т в исходной программе, является терминальным. Следовательно от данной семантической программы требуется только занести символ '+' в польскую запись P...<код для Е2><код для Т>+.

Т.е. инфиксная запись Е2переводится в польскую запись Е2Т+.

Итак, семантическая программа имеет следующий вид:

P[J]:='+'; J:=J+1.

Семантическая программа, связанная с правилом F::=id, имеет вид

P[J]:=S[i]; J:=J+1,

где S[i] - это вершина синтаксического стека.

Семантическая программа, связанная с правилом F::=(E), никаких действий не производит, т. к. цепочка для Е уже сформирована, а приоритет операции в польской записи задается порядком следования операндов и операторов, т. е. без применения скобок.

Все типы семантических программ для грамматики алгебраических выражений приведенной выше можно свести в следующую таблицу.

N

Правило

Семантическая программа

1

Z::=E

нет

2

E::=T

нет

3

E::=E+T

P[J]:='+'; J:=J+1;

4

E::=E-T

P[J]:='-'; J:=J+1;

5

E::=-T

P[J]:='@'; J:=J+1;

6

T::=F

нет

7

T::=T*F

P[J]:='*'; J:=J+1;

8

T::=T/F

P[J]:='/'; J:=J+1;

9

F::=id

P[J]:=S[i]; J:=J+1;

10

F::=(E)

нет

Примеры:

id1+id2*id3 в польской записи -> id1 id2 id3 * +

a*b+c -> a b * c +

a + b + c -> a b + c +

c * (a + b) -> cab+ *

a+b*c+d -> abc*+d+

Обратная польская запись(как польская запись только в польской +АБ а тут АБ+,по умному “постфиксная”)

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

Вход: 3 + 4 * 2 / (1 - 5)^2

Читаем «3»

Добавим «3» к выходной строке

Выход: 3

Читаем «+»

Кладём «+» в стек

Выход: 3

Стек: +

Читаем «4»

Добавим «4» к выходной строке

Выход: 3 4

Стек: +

Читаем «*»

Кладём «*» в стек

Выход: 3 4

Стек: + *

Читаем «2»

Добавим «2» к выходной строке

Выход: 3 4 2

Стек: + *

Читаем «/»

Выталкиваем «*» из стека в выходную строку, кладём «/» в стек

Выход: 3 4 2 *

Стек: + /

Читаем «(»

Кладём «(» в стек

Выход: 3 4 2 *

Стек: + / (

Читаем «1»

Добавим «1» к выходной строке

Выход: 3 4 2 * 1

Стек: + / (

Читаем «-»

Кладём «-» в стек

Выход: 3 4 2 * 1

Стек: + / ( -

Читаем «5»

Добавим «5» к выходной строке

Выход: 3 4 2 * 1 5

Стек: + / ( -

Читаем «)»

Выталкиваем «-» из стека в выходную строку, выталкиваем «(»

Выход: 3 4 2 * 1 5 -

Стек: + /

Читаем «^»

Кладём «^» в стек

Выход: 3 4 2 * 1 5 -

Стек: + / ^

Читаем «2»

Добавим «2» к выходной строке

Выход: 3 4 2 * 1 5 - 2

Стек: + / ^

Конец выражения

Выталкиваем все элементы из стека в строку

Выход: 3 4 2 * 1 5 - 2 ^ / +