Часть II. Формальное описание языков программирования ( Формальная спецификация формальных языков ) Введение. Атрибутные грамматики.

Презентация:



Advertisements
Похожие презентации
Часть II. Формальное описание языков программирования ( Формальная спецификация формальных языков ) Введение. Атрибутные грамматики.
Advertisements

Часть II. Формальное описание языков программирования ( Формальная спецификация формальных языков ) Приложение. Атрибутная грамматика языка IMP.
Часть II. Формальное описание языков программирования ( Формальная спецификация формальных языков ) Атрибутные грамматики (2). Генерация кода.
Семантический анализ КC-грамматики, с помощью которых описывают синтаксис языков программирования, не позволяют задавать контекстные условия (КУ), имеющиеся.
Часть II. Формальное описание языков программирования ( Формальная спецификация формальных языков ) Приложение. Операционная семантика языка SIL.
Часть II. Формальное описание языков программирования ( Формальная спецификация формальных языков ) Операционная семантика.
Преобразования типов В языке C/C++ имеется несколько операций преобразования типов. Они используются в случае, если переменная одного типа должна рассматриваться.
Тест классы По программированию Pascal.
КЛАССИФИКАЦИЯ ГРАММАТИК И ЯЗЫКОВ ( КЛАССИФИКАЦИЯ ХОМСКОГО ) Рейн Т. С.
М.Ю. Харламов, ВНУ им. В.Даля, Семантический анализатор Семантический анализатор выполняет следующие основные действия: проверку соблюдения во входной.
Троицкий Д.И. Лингвистическое и программное обеспечение САПР 1 Классификация грамматик и языков Лекция 9 Кафедра «Автоматизированные станочные системы»
Все процедуры и функции делятся на стандартные встроенные определенные пользователем. Встроенные и стандартные вызываются без предварительного описания.
ЦИКЛИЧЕСКИЙ АЛГОРИТМ Цели: -Познакомиться с понятием циклического алгоритма. -Освоить языковые средства для реализации циклических алгоритмов.
Практическое занятие 6. Функции. Большинство языков программирования используют понятия функции и процедуры. C++ формально не поддерживает понятие процедуры,
Лекция 3 Операторы Цикла 1 Российский государственный университет нефти и газа имени И.М. Губкина Кафедра «Информатики»
Что такое программирование? Совокупность процессов, связанных с разработкой программ и их реализацией. В широком смысле к указанным процессам относят все.
Глава 6. УПРАВЛЯЮЩИЕ СТРУКТУРЫ Оператор присваивания Простой и составной операторы Условный оператор Оператор множественного выбора Оператор цикла с предусловием.
Глава 1. Язык реализации: TSG. Супер- компиляция scp Специализация программ Приложения суперкомпиляции, в том числе Базовые понятия и методы метавычислений.
Процедуры и функции Вербицкая Ольга Владимировна, Заозерная школа 16.
Транксрипт:

Часть II. Формальное описание языков программирования ( Формальная спецификация формальных языков ) Введение. Атрибутные грамматики

План 1.Цели и задачи формального описания языков программирования 2.Синтаксис, семантика, прагматика (статическая и динамическая семантики) 3.Подходы к описанию (контекстно-свободного) синтаксиса 4.Подходы к описанию контекстно-зависимого синтаксиса (статической семантики) 5.Подходы к описанию (динамической) семантики

Цели 1.Автоматическая генерация программ 2.Автоматическая верификация 3.Недвусмысленное (строгое) описание языка 4.Апробация новых концепций при разработке новых языков

Задачи формального описания Описание контекстных зависимостей (статической семантики) 1.Описать требования к (статически) корректной программе (для пользователя языка, для разработчика тестов компилятора, для разработчика компилятора) 2.Сформировать исходные данные для генератора фронт-процессора Описание «смысла», динамической семантики 1.Описать эталон, с которым можно сравнивать результаты выполнения скомпилированной программы 2.Сформировать исходные данные для генератора кода компилятора 3.Описать правила (аксиомы) эквивалентности, которые можно использовать для построения оптимизаторов 4.Описать правила (аксиомы) эквивалентности, которые можно использовать для верификации оптимизаторов Спецификация блоков компилятора и компилятора в целом 1.Сформировать исходные данные для построения тестов для компилятора в целом и для отдельных блока компилятора

Семантические свойства (аспекты) языка 1.Передача параметров (по значению, по ссылке,...) 2.Порядок вычислений параметров функций 3.Области видимости имен 4.Размещение данных в памяти 5.Обработка исключений, более широко, поведение при ненормальном ходе вычислений 6.Синхронизация и взаимодействие параллельных ветвей (нитей) программы 7.Динамическое связывание программ 8.Сбор мусора

Другие приложения формальных описаний языков 1.Разработка и тестирование протокольных сообщений (язык построения заголовков) 2.Генерация html документов, тестирование процессоров html документов, например, браузеров. 3.Генерация XML документов, тестирование процессоров XML документов 4.Какие еще области используют формальные языки?

Синтаксис, семантика (статическая и динамическая), прагматика Синтаксис - структура, Семантика –статическая - корректность –динамическая - смысл, Прагматика – назначение

Язык и грамматика Язык 1 – множество предложений. Грамматика – множество правил, которые описывают порождение предложений языка. Язык 2 – множество предложений, которые порождаются из данной грамматики. Синтаксис – описание структуры предложений. Структура – набор элементов и связей между ними. Каждому слову сопоставляется его (грамматическая) роль и задаются связи между словами, между группами слов (фразами). Контекстно-свободные грамматики, контекстно-свободный синтаксис. Контекстно-зависимый синтаксис (context-sensitive, статическая семантика)

Грамматика Алфавит: конечный набор символов Σ Строки: конечные цепочки символов Пустая строка ε Σ* - множество всех возможных строк из символов Σ (включая ε) Σ+ - множество всех непустых строк из символов Σ Язык: множество строк L Σ*

Грамматики G = (N, T, S, P) Конечное множество нетерминальных символов N Конечное множество терминальных символов T Стартовый нетерминальный символ S N Конечное множество продукций P Продукция: x y x (N T) +, y (N T)* Применение продукции: uxv ayb

Языки и грамматики Вывод строки w 1 w 2 … w n ; обозначается как w 1 w n Язык, которые генерируется грамматикой L(G) = { w T* | S w } Традиционная классификация –Регулярные (Regular) –Контекстно-свободные (Context-free) –Контекстно-зависимые (Context-sensitive) –Все остальные (Unrestricted)

Контекстно-свободные (КС) языки Выход за границы регулярных языков –L = { a n b n | n > 0 } КС, но не регулярный Генерируется КС грамматикой Все продукции имеют вид: A w, где –A N, w (N T)* BNF: –Backus-Naur form: John Backus and PeterNaur, for ALGOL60

Пример расширенной BNF (EBNF) ::= while do | if then [ else ] | := | ( {, } ) Введены сокращения: [ … ] - цепочка, которая может быть опущена { … } - цепочка, которая может отсутствовать или повторяться некоторое число раз

Дерево вывода Другие названия: дерево разбора (parse tree) или дерево конкретного синтаксиса (concrete syntax tree) –Листья - терминалы –Внутренние узлы - нетерминалы –Корень – стартовый нетерминал грамматики Описывает конкретный путь вывода заданной строки –Узлы-листья слева направо составляют заданную входную цепочку обход графа «сначала вглубь», начиная с самой левой непройденной вершины

Пример дерева вывода

Ограничения КС грамматик Не могут представлять семантику, например –«каждая переменная должна быть описана ранее, чем она используется» –«использование переменной должно быть согласовано с ее типом» –не описывает действия, которые скрываются за тексом, например «строка» s1 делится на «строку» s2 Решение: атрибутные грамматики –Определенный вид описания семантики

Атрибутные грамматики КС грамматика (BNF) Конечное множество атрибутов –Для каждого атрибута – область возможных значений –Для каждого терминала и нетерминала – можесвто ассоциированных с ним атрибутов (возможно, пустое) Наследуемые (inherited) и синтезируемые (synthesized) Множество правил вычисления атрибутов Множество булевских условий, заданных на значениях атрибутов

Пример L = { a n b n c n | n > 0 } – не КС BNF ::= ::= a | a ::= b | b ::= c | c Атрибуты –Na: ассоциирован с –Nb: ассоциирован с –Nc: ассоциирован с –Область значений = integers

Пример Правила вычисления (аналогично для, ) ::= a Na( ) := 1 | a 2 Na( ) := 1 + Na( 2) Условия ::= Cond: Na( ) = Nb( ) = Nc( ) Альтернативная нотация -.Na

Дерево разбора

Дерево разбора для некоторой атрибутной грамматики Корректное дерево для опорной (underlying) BNF Каждый узел имеет свой набор пар (атрибут-значение) Некоторые узлы имеют булевские условия Корректное дерево разбора –Значения атрибутов отвечают правилам их вычисления –Все булевские атрибуты (условия) истинны

Пример – блок в языке Ada x: begin a := 1; b := 2; end x; ::= 1 : begin end 2 ; –Cond: value( 1) = value( 2) ::= | ::= id –value( ) := id

Другой способ задания условий.OK := 1.value = 2.value Все узлы типа должны иметь.OK = true

Синтезируемые vs. наследуемые атрибуты Синтезируемые атрибуты вычисляются, используя значения из деревьев-потомков –Продукция - ::= … –Правило вычисления -.syn := … Наследуемые – значения из узла-родителя –Продукция - ::= … … –Правило вычисления -.inh := … В обоих случаях правила вычисления могут иметь произвольную сложность

Синтезируемые и наследуемые атрибуты syn inh

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

Пример: двоичные числа КС грамматика Для простоты будем писать X вместо B ::= D B ::= D B D ::= 0 D ::= 1 Цель – вычислить значение двоичного числа

Пример: двоичные числа (2) B ::= D B.pos := 1 B.val := D.val D.pow := 0 B1 ::= D B2 B1.pos := B2.pos + 1 B1.val := B2.val + D.val D.pow := B2.pos D ::= 0 val := 0 D ::= 1 D.val := 2 D.pow (возведение в степень) ADD attributes B: syn val B: syn pos D: inh pow D: syn val

Дерево разбора с вычисленными атрибутами

КС грамматика ::= ::= begin ; end ::= | ; ::= | |...

Задачи Проверить типы переменных (int, bool) Для вложенных блоков использовать самые внутренние декларации (static scoping) Проверять типы параметров и тип возвращаемого значения в функциях –Например, все функции имеют тип результата int

Дерево разбора prog | block ДекларацииОператоры

Структура данных Использовать стек групп пар вида имя- тип –стек «таблиц символов» Строить таблицы символов для деклараций в блоках –синтезируемый атрибут tbl Использовать стек таблиц символов в операторах и выражениях –наследуемый атрибут symtab

Пример – проверка типов begin bool i; int j; begin int i; x := i + j; end Верхушка стека [ {("i",INT)}, {("i",BOOL), ("j",INT)} ] База стека

Атрибутная грамматика ::=.symtab := emptystack ::= begin ; end.symtab := push(.tbl,.symtab) 1 ::=.symtab := 1.symtab | ; 2.symtab := 1.symtab 2.symtab := 1.symtab

Декларации 1 ::= 1.tbl :=.tbl | ; 2 1.tbl :=.tbl 2.tbl Условие: ids(.tbl) ids( 2.tbl) = ids – функция, которая получает множество вида имя-тип и возвращает множество всех имен

Декларации ::= int.tbl := { (.name, INT) } | bool.tbl := { (.name, BOOL) } | fun ( ) : int =.tbl := { (.name, FUN(.types, INT) ) }.symtab := Oops!……. Синтезируемый атрибут - упорядоченный список INT/BOOL

Возврат к.symtab Декларации добавляются в наследуемый атрибут symtab ::= begin ; end.symtab := push(.tbl,.symtab).symtab := push(.tbl,.symtab) Сначала берем декларации в, потом используем их для проверок блоков встроенных в

Декларации 1 ::= 1.tbl :=.tbl | ; 2 1.tbl :=.tbl 2.tbl.symtab := 1.symtab 2.symtab := 1.symtab Cond: ids(.tbl) ids( 2.tbl) =

Декларации ::= int.tbl := { (.name, INT) } | bool.tbl := { (.name, BOOL) } | fun ( ) : int =.tbl := { (.name, FUN(.types, INT) ) }.symtab := push(.tbl,.symtab)

Проверка типов в теле функции fun f (int i): int = begin... g(5)... end; fun g (int j): int = begin... end

Операторы 1 ::=.symtab := 1.symtab | ; 2.symtab := 1.symtab 2.symtab := 1.symtab ::=.symtab :=.symtab |.symtab :=.symtab | if then else....symtab :=.symtab

Операторы ::= :=.symtab :=.symtab typeof(.name,.symtab) = INT | :=.symtab :=.symtab typeof(.name,.symtab) = BOOL

Выражения 1 ::= | Cond: typeof(.name, 1.symtab) = INT | symtab := 1.symtab 3.symtab := 1.symtab ::= true | false | Cond: typeof(.name,.symtab) = BOOL

Вызов функции (Function Call) ::= ( ) Cond: typeof(.name,.symtab) = FUN Cond: rettype(.name,.symtab) = INT.expTypes := paramtypes(.name,.symtab).symtab :=.symtab