1 / 45

Введение. Атрибутные грамматики

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

renee
Download Presentation

Введение. Атрибутные грамматики

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  22. Пример –блок в языке Ada x: begin a := 1; b := 2; end x; • <block> ::= <block id>1 : begin<stmts> end <block id>2 ; • Cond: value(<block id>1) = value(<block id>2) • <stmts> ::= <stmt> | <stmts> <stmt> • <block id> ::= id • value(<block id>) := id

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

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

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

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

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

  28. Пример: двоичные числа (2) • ADD attributes • B: syn val • B: syn pos • D: inh pow • D: syn val 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 := 2D.pow(возведение в степень)

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

  30. КС грамматика <prog> ::= <block> <block> ::= begin <decls> ; <stmts> end <stmts> ::= <stmt> | <stmt> ; <stmts> <stmt> ::= <assign> | <block> | ...

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

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

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

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

  35. Атрибутная грамматика <prog> ::= <block> <block>.symtab := emptystack <block> ::= begin <decls> ; <stmts> end <stmts>.symtab := push(<decls>.tbl, <block>.symtab) <stmts>1 ::= <stmt> <stmt>.symtab := <stmts>1.symtab | <stmt> ; <stmts>2 <stmt>.symtab := <stmts>1.symtab <stmts>2.symtab := <stmts>1.symtab

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

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

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

  39. Декларации <decls>1 ::= <decl> <decls>1.tbl := <decl>.tbl | <decl>;<decls>2 <decls>1.tbl := <decl>.tbl <decls>2.tbl <decl>.symtab := <decls>1.symtab <decls>2.symtab := <decls>1.symtab Cond: ids(<decl>.tbl) ∩ ids(<decls>2.tbl) = 

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

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

  42. Операторы <stmts>1 ::=<stmt> <stmt>.symtab := <stmts>1.symtab | <stmt> ; <stmts>2 <stmt>.symtab := <stmts>1.symtab <stmts>2.symtab := <stmts>1.symtab <stmt> ::= <assign> <assign>.symtab := <stmt>.symtab | <block> <block>.symtab := <stmt>.symtab | if <boolexp> then <stmts> else ... <boolexp>.symtab := <stmt>.symtab <stmts>.symtab := <stmt>.symtab

  43. Операторы <assign> ::= <id> := <intexp> <intexp>.symtab := <assign>.symtab typeof(<id>.name,<assign>.symtab) = INT | <id> := <boolexp> <boolexp>.symtab := <assign>.symtab typeof(<id>.name,<assign>.symtab) = BOOL

  44. Выражения <intexp>1 ::= <integer> | <id> Cond: typeof(<id>.name, <intexp>1.symtab) = INT | <intexp>2+<intexp>3 <intexp>2.symtab := <intexp>1.symtab <intexp>3.symtab := <intexp>1.symtab <boolexp> ::= true | false | <id> Cond: typeof(<id>.name, <boolexp>.symtab) = BOOL

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

More Related