
- •Теория языков программирования и методы трансляции
- •1. Языки и кризис программирования.
- •2. Математические методы описания языков программирования.
- •3. Основные понятия и определения.
- •1. S→ab→aAb→aaAb→aaaB→aaabB→aaabbB→aaabbbB→aaabbbb.
- •2. S→ab→AbB→AbbB→AbbbB→Abbbb→aAbbbb→aaAbbbb→aaabbbb
- •Load a mult b
- •4. Этапы построения транслятора.
- •5. Основные методы поиска ошибок в исходных текстах программ.
- •Устройство управления
- •6. Современное состояние и перспективы развития программирования трансляторов.
- •7. Лексический анализ. Интуитивный подход.
- •8. Классы лексем и их особенности.
- •9. Формирование таблиц лексем и построение дескрипторного текста исходной программы.
- •На основании составленных таблиц можно записать входной текст через введённые дескрипторы (дескрипторный текст):
- •10. Синтаксический анализ. Метод рекурсивного спуска.
- •11. Пример грамматики упрощенного языка Паскаль.
- •12. Пример программы на упрощенном Паскале.
- •Var sum, sumsq, I, value, mean, variance : integer;
- •13. Алгоритм синтаксического анализа по методу рекурсивного спуска.
- •Void read()
- •Void idlist()
- •Void assign()
- •15. Лексический анализ, регулярные грамматики и конечные автоматы.
- •17. Грамматики типа ll(k). Алгоритмы построения магазинных анализаторов.
- •18. Детерминированный синтаксический анализ сверху вниз.
- •19. Правила определения детерминированного мп-разпознавателя по ll(1) грамматике.
- •20. Заключение.
- •Литература
Void read()
{
found=false; // Установка признака синтаксической ошибки
if(token==1.6 “read”) // Если считана лексема read
if(token==2.9 “(” // Если считана лексема (
if(token==2.11“id”) id-list; // Происходит обращение к процедуре
ID-LIST
if(token==2.10 “)” found=true; // Признак успеха }
Void idlist()
{
found=false; // Установка признака синтаксической ошибки
if(token==2.11 “id”) found=true;
if((token == 2.3 “,”) and (found==true)) do
{if(token== 2.11”id”)nexttoken() else
found=false;}
while (token==2.10 “)”);
if(token==2.10 “)”) found=true;
}
Пример синтаксического анализа оператора присвоения. Обратимся к примеру программы на упрощенном Паскале. Строка 9.
sum:=sum+value;
Void assign()
{
found=false;
if(token== 2.11”id”) nexttoken();
if(token== 2.4“:=”)exp();
if(found==true)found=true;
}
void exp()
{
found=false;
if((token== 2.5”+”)||(token== 2.6“-“)||(token== 2.11“id”)||(token== 2.9“(“))
{term();
if(found==true) found=true;}
}
void term()
{
}
void factor()
{
}
14. Формализация методов построения трансляторов. Формальные языки и грамматики. Классификация формальных языков по Хомскому.
Построение трансляторов для языков высокого уровня сложная задача, которая требует формализации всех её этапов. Эта формализация в первую очередь требует формального описания языков программирования.
Практическое применение грамматик связано решением проблемы распознавания. Проблема распознавания разрешима, если существует такой алгоритм, который за конечное число шагов даёт ответ на вопрос принадлежит ли произвольная строка языку, порождённому заданной грамматикой. Если такой алгоритм существует, то язык называется распознаваемым. На практике рассматриваются такие частные классы порождающих грамматик, которые соответствуют распознаваемым и легко распознаваемым языкам. Язык легко распознаваем, если для некоторой строки, число шагов алгоритма можно оценить заранее.
Наиболее важные классы таких языков могут быть определены в рамках классификации языков по Хомскому, который предложил классифицировать формальные языки по типу продукций порождающих их грамматик.
Класс 0. Правила вывода грамматики не имеют никаких ограничений. Пример естественный язык.
Класс 1. Порождён контекстно зависимой грамматикой. Языки класса 1 могут порождаться грамматикой, правая часть продукций которой не короче её левой части в каждом случае. Длина строки в такой грамматике может только возрастать. Такие грамматики называют не укорачивающими.
Класс 2. Язык порождается КС грамматикой. Если алфавит языка допускает пробел. И пробел является терминальным символом, то такая грамматика называется укорачивающей УКС грамматикой. УКС и КС грамматики почти эквивалентны. УКС грамматики описывают языки программирования. Изучение УКС грамматик можно свести к изучению КС грамматик. КС грамматики играют главную роль при формальном изучении синтаксиса языков программирования и построения блока синтаксического анализа транслятора.
Грамматика
типа
Машины
Тьюринга Рекурсивно
перечисляемые множества0
Контекстные
языки Линейно-ограниченные автоматы1
Контекстно-свободные
языки Автоматы
с магазинной памятью2
Регулярные
языки Конечные
автоматы3
Рис.14.1 Классификация формальных языков по Хомскому.
Класс 3. Язык порождается регулярной грамматикой. Языки класса 3 называются языками с конечным числом состояний или автоматными (регулярными) языками. Они используются в основном на этапе лексического анализа.
Связь между приведёнными классами языков и проблемой распознавания формулируется следующей теоремой: «Язык, порождаемый не укорачивающей грамматикой легко распознаваем.
Иерархия языков в соответствии с классификацией Хомского определяется следующей теоремой: «Если язык регулярный, то он контекстно-свободный. Если язык контекстно-свободный, то он контекстный. Если язык контекстный, то он класса 0. Отсюда иерархия языков сверху вниз.
Регулярные языки. Если ε входит в множество {T}, то запись А→ε корректна. Эту продукцию назовём ε-продукцией. Наличие ε-продукции осложняет как процедуру грамматического разбора так и использование грамматики для описания формального языка. Грамматика, не имеющая ε-продукций, называется ε-свободной грамматикой. Если язык Ɫ(G) содержит ε, то можно преобразовать КС грамматику G в грамматику G/, которая бы была ε-свободной грамматикой выполнялось бы условие
Ɫ(G|) = Ɫ(G)/{ε}.
Пусть G(N,T,P,S) Кс грамматика, имеющая ε-продукции. Например,
S→[E}|E
Е→T|E+T|E-T
T→F|T*F|T/F
F→a|b|c|ε
При этом возможны следующие транзитивные замыкания:
S→ε, E→ε, T→ε, F→ε
т.е. из Этих нетерминальных символов можно последовательно перейти к пробелу ε. Учтём это в новых продукциях:
S→[E]|E|[ ]
E→T|Е+F|Е-F|E+|E-|+T|-T|+|-
T→F|T*F|T/F|T*|T/|*F|/F|/|*
F→a|b|c
Таким образом, мы получили новую грамматику, эквивалентную исходной, но ε-свободной. В этой грамматики будут только новые продукции.
Теорема. Для любого КС языка Ɫ существует ε-свободная КС грамматика G, такая что Ɫ(G) = Ɫ/{ε}.
Регулярные грамматики. КС грамматика G(N,T,P,S) называется регулярной грамматикой, если:
1. Она имеет ε-продукцию вида S→ε и ни одна из оставшихся продукций G не содержит в своей правой части нетерминального символа S;
2. Все остальные продукции грамматики G имеют вид
A→a|aA
Язык называется регулярным языком, если он порождён регулярной грамматикой. Регулярный язык порождается ε-свободной грамматикой.
Пример. При компилировании исходного модуля программы большая часть времени расходуется на распознание символов языка программирования. Целесообразно применить грамматику имеющую продукция такого же вида. Это и будет регулярная грамматика, порождающая регулярные языки.
Пусть требуется описать всё множество целых чисел. Это легко сделать с помощью регулярной грамматики, имеющей продукцию:
С→0|1|2|3|4|5|6|7|8|9|0C|1C|2C|3C|4C|5C|6C|7C|8C|9C.
С – аксиома языка. Для целого числа 467 цепочка вывода будет иметь вид
С→4С→46С→467.