
- •Компиляция. Основные понятия. Контекст компилятора
- •Этапы, фазы и проходы
- •Фаза анализа. Основные понятия.
- •Фаза синтеза. Основные понятия.
- •Методы определения языка
- •Понятие регулярных выражений
- •Понятие грамматики
- •8.Иерархия грамматик по Хомскому
- •9 . Порождения синтаксические деревья
- •Неоднозначность
- •11.Понятие лексического анализа
- •12.Лексический анализ с помощью регулярных выражений
- •Лексический анализ с помощью конечных автоматов
- •14. Лексический анализ с помощью Lex
- •15. Нисходящий анализ. Критерии принятия решений.
- •16. Понятие ll(1)-грамматики
- •17. Рекурсивный спуск. Расширенная форма записи правил для исключения рекурсивных вызовов.
- •18. Рекурсивный спуск. Комбинирование рекурсии и итерации.
- •19. Преобразование грамматик. Удаление левой рекурсии
- •20. Преобразование грамматик. Факторизация
- •21. Введение действий в грамматику
- •22. Восходящий синтаксический анализ. Основные понятия. Критерий принятия решений
- •Восходящий синтаксический анализ. Таблица синтаксического анализа.
- •25. Характеристический конечный автомат.
- •Восходящий синтаксический анализ. Slr(1), lalr(1), общий алгоритм формирования таблицы lr(1)-анализа.
- •Восходящий синтаксический анализ. Генератор восходящих анализаторов yacc. Основные понятия.
- •Семантический анализ. Не-контекстно-свободные характеристики языков.
- •Семантический анализ. Таблица символов.
- •Семантический анализ. Таблица типов.
- •31.Семантический анализ. Таблицы функций. Таблицы меток
- •32. Распределение памяти. Классификация памяти
- •33. Распределение памяти. Стек времени выполнения. Определение области видимости.
- •34. Распределение памяти. Стековый фрейм.
- •35. Распределение памяти. Дисплей.
- •35. Адреса времени компиляции. Простые адреса. Адресация элементов статического массива.
- •37. Распределение памяти. Адреса времени компиляции. Адреса динамического массива
- •38. Куча. Основные понятия. Методы автоматического освобождения памяти.
17. Рекурсивный спуск. Расширенная форма записи правил для исключения рекурсивных вызовов.
Синтаксический анализ методом рекурсивного спуска включает использование рекурсивных процедур и работает нисходящим образом.
PROGRAM begin DECLIST comma STATELIST end
Использование синтаксического анализа методом рекурсивного спуска состоит из последовательного определения всех символов правой части. Появление слова begin определяется посредством вызова лексического анализатора, DECLIST определяется вызовом функции, именуемой DECLIST, comma определяется непосредственно, с помощью лексического анализатора, STATELIST определяется посредством вызова функции, именуемой STATELIST, наконец, end определяется непосредственно, снова с помощью лексического анализатора.
DECLIST d semi DECLIST | d
STATELIST s semi STATELIST | s
Метод рекурсивного спуска может применяться только к LL(1)-грамматикам, но данная грамматика, очевидно, такой не является, поскольку
DS(DECLIST d semi DECLIST | d) = {d}
DS(DECLIST d) = {d}
d
d semi d
d semi d semi d
d(semi d)*
DECLIST dX
X semi DECLIST |
STATELIST dY
Y semi STATELIST |
DS(X semi DECLIST ) = {semi}
DS(X ) = {comma}
DS(Y semi STATELIST ) = {semi}
DS(Y ) = {end}
void PROGRAM!) /*соответствует PROGRAM*/
{ if (token != begin) error{); token = lexical(); DECLIST();
if(token! = comma) error(); token = lexical(); STATELIST();
if (token! = end) error();}
void DECLIST()
{ if (token! = d) error(); token = lexical(); X();}
void X()
{ if (token == semi) {token = lexical(); DECLIST{);}
else if(token == comma) ; /*ничего не делать*/ else error();
void STATELIST(){ if (token! = s) error(); token = lexical; Y();}
void Y(){ if(token == semi){token = lexical(); STATELIST();}
else if(token == end) ; /*ничего не делать*/else error();
main ()
{ token = lexical (); PROGRAM();}
18. Рекурсивный спуск. Комбинирование рекурсии и итерации.
PROGRAM begin DECLIST comma STATELIST end
DECLIST d(semi d)*
STATELIST s(semi s)*
Программа синтаксического анализа, созданная на основе
расширенной формой записи, будет использовать уже не
рекурсию, а итерации.
void DECLIST()
{ if(token != d) error(); token = lexical();
while(token == semi) {token = lexical(};
if (token! = d) error(); token = lexical()}};
void STATELIST()
{ if(token! = s) error(); token = lexical();
while(token == semi)
{token = lexical(); if (token != s) error();
token = lexical();}}
Грамматики для языка 2-го типа будут содержать среднюю рекурсию и это нельзя заменить итерацией. Рассмотрим следующую грамматику в которой терминалы заключены в кавычки.
E → E“+”T E → TX E → T(“+”T)*
E → T X → “+”TX T → F(“*”T)*
T → T“*”F X → ε F → “(”E“)”
F → “(”E“)” T → FY F → “x”
F → “x” Y → “*”FY
Y → ε S → E
F → “(”E“)”
F → “x”
void E()
{Т();
while (token == plus) {token = lexical(); T()}
}
void T()
{F();
while (token == times) {token = lexical(); F();}
}
void F()
{ if(token == obracket) {token = lexical(); E();
if (token == cbracket) token = lexical(); else error();}
else
if (token == x) token = lexical(); else error();
}
main(){token = lexical; E();}