Дискуссионный математический форумМатематический форум

Математический форум Math Help Planet

Обсуждение и решение задач по математике, физике, химии, экономике

Теоретический раздел
Часовой пояс: UTC + 4 часа [ Летнее время ]
MathHelpPlanet.com RSS-лента Математического форума

Часовой пояс: UTC + 4 часа [ Летнее время ]


Семантика формальных языков

Семантика формальных языков


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


Необходимость в построении точного математического понятия "смысла" диктуется развитием информационных технологий, прежде всего технологии проектирования компиляторов.


Рассмотренные выше языковые модели определенным образом связаны с этапами этой технологии.


Текст входной программы, как известно, анализируется в несколько проходов. На первом проходе производится лексический анализ, а именно проверяется правильность простейших элементов текста, называемых лексемами. Примерами лексем могут служить идентификаторы и константы, разрешенные синтаксисом входного языка программирования. В процессе лексического анализа не проверяется синтаксическая правильность всей программы в целом, а проверяется только синтаксическая правильность лексем (в частности, правильность написания идентификаторов и констант). Так как лексемы обычно являются элементами некоторого регулярного языка, то базовой моделью для лексического анализатора является модель конечного автомата.


Если текст программы успешно прошел этап лексического анализа, то тогда проверяется его глобальная синтаксическая правильность. При этом каждая лексема рассматривается как буква. Здесь применяются методы синтаксического анализа, в частности рассмотренные ранее. В предположении, что синтаксис языка программирования описан КС-грамматикой, основой для построения синтаксических анализаторов, как мы уже видели, выбирается модель МП-автомата.


По завершении синтаксического анализа строится дерево вывода входной программы. После этого переходят к этапу генерации объектного кода, т.е. внутреннего машинного представления входного текста. Это значит, что выполняется перевод с некоторого языка программирования на язык машинных кодов. Но чтобы выполнить перевод текста на другой язык, необходимо каким-то образом понять его "смысл". Следовательно, анализ уже синтаксически проверенной программы с точки зрения ее "смысла" (семантический анализ) необходимо предшествует самой генерации объектного кода. И прежде всего необходимо уточнить математически, что такое "смысл" (как раньше мы математически определяли синтаксис в терминах грамматик и автоматов).


В этом дополнении мы рассмотрим некоторые методы формального (математического) определения семантики для КС-языков. Тем самым мы всюду в дальнейшем предполагаем, что язык, семантика которого определяется, может быть задан некоторой КС-грамматикой.


Сразу же необходимо сделать уточнение. Как мы уже заметили ранее, исследуя явление неоднозначности в КС-языках, "смысл" следует сопоставлять не самим словам языка, а деревьям их вывода: меняя дерево вывода данной цепочки, мы меняем и ее "смысл", понимаем ее по-другому. Далее, можно сопоставлять "смысл" не только словам языка, точнее, деревьям вывода этих слов из аксиомы грамматики, но и так называемым фразам языка — терминальным цепочкам, выводимым из разных нетерминалов грамматики.


Например, фраза "...а так как мне бумаги не хватило" не является законченным предложением русского языка, но имеет, очевидно, какой-то "смысл". Точно так же оператор присваивания, "вынутый" из какой-то программы на каком-то языке программирования, не является "программой", не может рассматриваться как элемент данного языка, но мы в состоянии сопоставить ему тот или иной "смысл". Тем самым возникает идея определить "смысл" через отображение множества "синтаксических объектов" — деревьев выводов фраз языка в некоторое "предметное множество", множество "семантических объектов".


Здесь мы ограничимся крайне элементарным введением в формальное описание семантики КС-языков и опишем некоторый простейший "кирпичик" формальной семантики языков программирования.




Формальное определение фразы КС-языка


Начнем с формального определения фразы КС-языка.


Определение 8.15. Пусть [math]G=(V,N,S,P)[/math] — КС-грамматика. Терминальную цепочку [math]x[/math] называют фразой языка [math]L(G)[/math], если [math]A\vdash^{\ast}x[/math] для некоторого нетерминала [math]A\in N[/math].


Пусть [math]T(x)[/math] — дерево вывода фразы [math]x[/math] с корневым нетерминалом [math]A[/math]. Возьмем в [math]T(x)[/math] некоторое поддерево с корневым нетерминалом [math]B[/math]. Выводимую из этого вхождения [math]B[/math] терминальную цепочку называют подфразой фразы [math]x[/math]. Если вершина дерева [math]T(x)[/math], соответствующая данному вхождению [math]B[/math], имеет глубину 1 (или, что равносильно, уровень, на единицу меньший уровня корня [math]A[/math]), то данная подфраза называется подфразой первого уровня фразы [math]x[/math].


Дерево вывода выражения

Рассмотрим в качестве примера следующую грамматику арифметических выражений:


[math]\begin{aligned}&Expr\to Atom\mid (Expr+Expr)\mid (Expr\ast Expr),\\ &Atom\to a_1\mid a_2\mid\ldots\mid a_n. \end{aligned}[/math]

Предполагается, что вместо вхождения нетерминала [math]Atom[/math] может быть подставлен любой символ некоторого алфавита [math]V=\{a_1,a_2,\ldots,a_n\}[/math] (атом в арифметическом выражении может быть либо переменным, либо константой). Нарисуем дерево вывода выражения


[math](a+(b\ast(c+(d\ast(e+g)))))[/math], где [math]a,b,c,d,e,g[/math] — некоторые атомы из [math]V[/math] (рис. 8.39).

Это выражение в качестве подфраз первого уровня имеет цепочки [math]a[/math] и [math](b\ast(c+(d\ast(e+g))))[/math]. Вторая фраза имеет подфразы первого уровня [math]b[/math] и [math](c+(d\ast(e+g)))[/math] и т.д. Заметим, что фраза [math]a[/math], выводимая из самого левого узла [math]Expr[/math] глубины 1 имеет в качестве подфразы первого уровня ту же цепочку [math]a[/math], т.е. подфраза первого уровня может совпадать с самой исходной фразой.


Множество всех фраз языка [math]L[/math] обозначим через [math]PH(L)[/math], а множество всех деревьев вывода фраз [math]L[/math] — через [math]TPH(L)[/math]. Для однозначного языка [math]L[/math] эти множества эквивалентны.




Семантическая функция языка L


Определение 8.16. Семантическая функция языка [math]L[/math] есть отображение


[math]SEM(L)\colon\, TPH(L)\to \mathbb{U}(L)[/math]

множества всех деревьев вывода фраз [math]L[/math] в некоторое множество [math]\mathbb{U}(L)[/math], называемое универсумом (предметной областью, семантической областью, областью интерпретации) языка [math]L[/math].


Замечание 8.14. Ради общности следовало бы определить семантическую функцию как частичное отображение, но мы не будем этого делать, вводя для "бессмысленных" фраз специальный "неопределенный" элемент в универсум ("нуль" предметной области, "неопределенный смысл"). Заметим также, что для однозначного языка семантическая функция может быть определена как отображение из множества фраз языка.


Способы определения семантической функции могут быть различными. Нас будет интересовать важный частный случай, когда значение семантической функции на некоторой фразе (под фразой здесь и далее понимается дерево ее вывода, причем разные деревья для одной и той же цепочки рассматриваются как разные фразы) определяется однозначно через значение этой функции на подфразах первого уровня. Более формально: представим фразу [math]x[/math] синтаксически как wсоединение" своих подфраз первого уровня:


[math]x=\varphi(y_1,y_2,\ldots,y_m)= u_1y_1u_2y_2\ldots u_my_mu_{m+1},[/math]
(8.28)

где [math]u_1,u_2,\ldots,u_{m+1}[/math] — некоторые терминальные цепочки. Например, для определенного выше языка арифметических выражений фраза, дерево вывода которой изображено на рис. 8.39 раскладывается следующим образом:


[math](a+(b\ast(c+(d\ast(e+g)))))= u_1au_2(b\ast(c+(d\ast(e+g))))u_3,[/math]

где [math]u_1[/math] есть цепочка (, [math]u_2[/math] — цепочка +, а [math]u_3[/math] — цепочка ).


Таким образом, любая фраза представляется, вообще говоря, не как простое соединение своих подфраз первого уровня, а как соединение с "прослойками" в виде определенных терминальных цепочек. Операцию [math]\varphi[/math] в (8.28), задающую такие прослойки, называют часто конкатенарной операцией. Эта операция определяется грамматикой языка.


Тогда предполагается, что если фраза [math]x[/math] представлена в виде (8.28), то определено отображнение [math]\psi\colon \mathbb{U}(L)^m\to\mathbb{U}(L)[/math] (т.е. некоторая операция на предметной области), такое, что


[math]SEM(L)(x)= \psi\bigl(SEM(L)(y_1),\ldots,SEM(L)(y_m)\bigr).[/math]
(8.29)

Это ограничение, накладываемое на семантическую функцию, назовем принципом гомоморфной интерпретации.


Примем теперь некоторые соглашения об обозначениях. Семантическую функцию языка [math]L[/math] будем обозначать [math][\kern-0.15em[\,\cdot\,]\kern-0.15em]_L[/math], опуская индекс, указывающий на язык, если это не ведет к недоразумению. Тогда равенство (8.29) можно переписать в виде


[math][\kern-0.15em[x]\kern-0.15em]= [\kern-0.15em[\varphi(y_1,\ldots,y_m)]\kern-0.15em]= \psi\bigl([\kern-0.15em[y_1]\kern-0.15em],\ldots, [\kern-0.15em[y_m]\kern-0.15em]\bigr).[/math]

Подобные определения семантики фразы через семантику ее подфраз первого уровня назьшают семантическими правилами языка. Семантические правила соответствуют синтаксическим правилам — правилам исходной КС-грамматики. Так, для приведенной выше грамматики арифметических выражений, полагая [math]\mathbb{U}=\mathbb{R}[/math], можно записать следующие семантические правила:


[math][\kern-0.15em[Expr]\kern-0.15em]= [\kern-0.15em[Expr]\kern-0.15em]+ [\kern-0.15em[Expr]\kern-0.15em].[/math]

(для синтаксического правила [math]Expr\to(Expr+Expr)[/math]), т.е. здесь конкатенарной операции [math]\varphi[/math], такой, что [math]\varphi(u,v)=(u+v)[/math] для любых двух фраз [math]u[/math] и [math]{v}[/math], сопоставляется обычное арифметическое сложение;


[math][\kern-0.15em[Expr]\kern-0.15em]= [\kern-0.15em[Expr]\kern-0.15em]\ast [\kern-0.15em[Expr]\kern-0.15em].[/math]

(для синтаксического правила [math]Expr\to(Expr\ast Expr)[/math]) операция на универсуме — арифметическое умножение;


[math][\kern-0.15em[Expr]\kern-0.15em]= [\kern-0.15em[Atom]\kern-0.15em][/math]

(для синтаксического правила [math]Expr\to Atom[/math]);


[math][\kern-0.15em[Atom]\kern-0.15em]= [\kern-0.15em[a_i]\kern-0.15em][/math] (для синтаксического правила [math]Atom\to a_i,~i=\overline{1,n}[/math]).

Строго говоря, в первых двух правилах мы должны различать три разных вхождения одного и того же нетерминала [math]Expr[/math], так как они соответствуют разным деревьям.


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


Так, для приведенного выше выражения, полагая [math][\kern-0.15em[ a ]\kern-0.15em]=1,~ [\kern-0.15em[ b ]\kern-0.15em]=2,~ [\kern-0.15em[ c ]\kern-0.15em]=3,[/math] [math][\kern-0.15em[ d ]\kern-0.15em]=4,~ [\kern-0.15em[ e ]\kern-0.15em]=5,~ [\kern-0.15em[ g ]\kern-0.15em]=6[/math], получим значение всего выражения, равное 95.


Таким образом, в этом конкретном случае семантика фразы есть числовое значение представленного данной фразой арифметического выражения. Мы рассмотрели в качестве универсума множество вещественных чисел и получили одну семантику. Задав универсум как-нибудь иначе (например, как множество комплексных чисел или множество функций некоторого класса), получим совсем другую семантику. Для одного и того же синтаксиса, следовательно, могут быть определены различные семантики (семантические функции).


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


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


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


Формальная теория задается как некоторый язык, цепочки которого называются в этом случае утверждениями (или предложениями). В этом языке определяется подъязык так называемых доказуемых утверждений: задается некоторое начальное множество утверждений, которые считаются априори доказанными (множество аксиом теории), и задается некоторое множество правил вывода, применяя которые к некоторым утверждениям (в частности, уже доказанным), можно получать новые утверждения. Если мы применяем правило вывода к доказанному утверждению, то получаем новое доказанное утверждение. Утверждение, которое таким образом может быть выведено из аксиом, называют теоремой данной теории. Утверждение считается имеющим смысл, если оно есть либо аксиома, либо теорема данной теории. В отличие от экстенсионального подхода при интенсиональном подходе априори не определяется никакой универсум, и при таком подходе к определению семантики "иметь смысл" означает "быть теоремой или аксиомой данной теории".


Вернемся к рассмотренному выше языку арифметических выражений. Зададим его в виде формальной теории следующего вида:


1) аксиома — любой атом [math]a_1,\ldots,a_n[/math];

2) правила вывода:


[math]e_1,e_2\Rightarrow (e_1+e_2),\quad (1)\quad\qquad e_1,e_2\Rightarrow (e_1\ast e_2),\quad (2)[/math]

т.е. если [math]e_1[/math] и [math]e_2[/math] доказаны, то доказано утверждение [math](e_1+e_2)[/math] и утверждение [math](e_1\ast e_2)[/math].


Построим, например, доказательство записанного выше выражения:


[math]\begin{array}{ll}a,b,c,d,e,g&\quad -\textx{aksiomy};\\ (e+g)&\quad - \text{pravilo vyvoda}~(1);\\ (d\ast (e+g))&\quad - (2);\\ (c+(d\ast (e+g)))&\quad - (1);\\ (b\ast(c+(d\ast (e+g))))&\quad - (2);\\ (a+(b\ast(c+(d\ast (e+g)))))&\quad - (1).\\ \end{array}[/math]

Нетрудно видеть, что мы определили тот же язык другим способом. Множество доказуемых утверждений совпадает здесь с множеством всех утверждений, и, таким образом, семантика в данном случае совпала с синтаксисом: утверждение имеет смысл тогда и только тогда, когда может быть доказано, т.е. тогда и только тогда, когда является арифметическим выражением, порождаемым приведенной выше грамматикой.


Замечание 8.15. В этой связи полезно заметить, что и правила вывода формальной теории следует трактовать как просто "правила замены" (в полной аналогии с порождающими грамматиками), согласно которым разрешается от определенных цепочек (в левой части правила) переходить к новым цепочкам (в правой его части).


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


Такая широкая и чисто синтаксическая трактовка правил вывода позволяет в теории формальных систем и в связанной с нею теории доказательств строить выводы из "гипотез" — цепочек, которые предполагаются доказанными. Если затем удается действительно доказать их, то построенное первоначально "относительное" доказательство превратится в "абсолютное" (т.е. начинающееся с аксиом).




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


В заключение рассмотрим экстенсиональное определение семантики простейшего языка программирования, который будем называть MILAN (MIniLANguage). Синтаксис языка определим посредством форм Бэкуса-Наура:


(программа) ::= (последовательность_операторов) (последовательность_операторов) ::= (оператор) |
(оператор) (последовательность_операторов) (оператор) ::= (присваивание) | (условный лереход) | (цикл) (присваивание) ::= (переменное) := (терм) (условный_переход) ::= if (условие) then
(последовательность_операторов) else (последовательность-операторов) | if (условие) then (последовательность_операторов) (цикл) ::= while (условие) do
(последовательность_операторов) end (переменное) ::= £i|...|zn (терм) ::= (функциональный_символ)
((последовательность_термов)) |
(переменное) | (константа) (последовательность_термов) ::= (терм) |
(терм) (последовательность_термов) (функциональный_символ) ::= [math]f_1\mid \ldots\mid f_m[/math]
(константа) ::= [math]c_1\mid \ldots\mid c_k[/math]
(условие) ::= (предикатный_символ)
((последовательность_термов))
(предикатный_символ) ::= [math]p_1\mid \ldots\mid p_s[/math]

Заданная таким образом КС-грамматика определяет так называемый абстрактный синтаксис MILANa: мы игнорируем некоторые синтаксические детали, такие, как слова begin, end, обрамляющие последовательность операторов, а также то, что операторы разделяются точкой с запятой, что между термами в последовательности термов ставится запятая и т.п. Мы также не уточняем структуру переменных (идентификаторов), констант, функциональных и предикатных символов, считая, что эти нетерминалы "пробегают" каждый свой алфавит.


Чтобы формально описать экстенсиональную семантику введенного посредством написанных выше синтаксических правил языка, нужно определить универсум. В зависимости от того, какой универсум рассматривается, в рамках экстенсионального подхода различают:


1) денотационную семантику;
2) операциональную семантику;
3) трансформационную семантику (семантику смешанных вычислений).
Здесь мы рассмотрим только денотационную семантику.

В денотационной семантике языка, подобного MILANy, универсум определяется как множество преобразователей состояний памяти. К построению этого множества и переходим.


Определение 8.17. Состояние памяти — это произвольное отображение множества переменных [math]I[/math] языка программирования в множество [math]D[/math] данных (значений).


В силу сформулированного определения мы отождествляем память с множеством переменных (идентификаторов, "ячеек", имен) данного языка программирования (конкретно — языка MILAN), а состояние памяти [math]\sigma[/math] есть отображение вида [math]\sigma\colon I\to D[/math], сопоставляющее каждой переменной значение, принадлежащее некоторому множеству значений (данных) [math]D[/math]. Последнее можно рассматривать как объединение некоторого семейства множеств, служащих носителями многосортной алгебры данных языка. Их можно отождествить с типами данных, используемыми в рассматриваемом языке: числами, массивами, строками, стуктурами и т.п. В множество [math]D[/math] включен также неопределенный элемент [math]\mathbb{O}[/math] (неопределенное значение). Множество всех состояний памяти обозначим [math]\Sigma[/math].


Определение 8.18. Преобразователь состояний памяти — это произвольное отображение множества [math]\Sigma[/math] состояний памяти в себя.


Множество всех преобразователей состояний памяти обозначим [math](\Sigma\to\Sigma)[/math].


На множестве [math]\Sigma[/math] определяется структура индуктивного упорядоченного множества.


Область определенности состояния памяти [math]\sigma[/math] — это множество, обозначаемое [math]D(\sigma)[/math], всех переменных [math]x[/math], таких, что [math]\sigma(x)\ne \mathbb{O}[/math].


Тогда положим для двух произвольных состояний [math]\sigma[/math] и [math]\rho[/math]


[math]\sigma\leqslant~\rho~ \Leftrightarrow \bigl(D(\sigma)\subseteq D(\rho)\bigr)\And \bigl((\forall x\in D(\sigma))(\sigma(x)=\rho(x))\bigr).[/math]

Очевидно, что отношение [math]\leqslant[/math] есть отношение порядка. Далее, множество [math]\Sigma[/math] имеет по отношению [math]\leqslant[/math] наименьший элемент, а именно такое состояние [math]\mathbb{O}[/math], что [math](\forall x\in I)(\mathbb{O}(x)= \mathbb{O})[/math]. Его называют всюду неопределенным состоянием памяти; ясно, что [math]D(\mathbb{O})=\varnothing[/math]. Кроме того, для любой неубывающей последовательности состояний памяти [math]\sigma_1\leqslant \sigma_2\leqslant \ldots\leqslant \sigma_n\leqslant\ldots[/math] состояние [math]\sigma_0[/math], такое, что [math]\sigma_0(x)= \sigma_n(x)\Leftrightarrow x\in D(\sigma_n)[/math], есть точная верхняя грань этой последовательности, причем [math]\textstyle{\mathop{D(\sigma_0)= \bigcup\limits_{n\geqslant1} D(\sigma_n)}\limits^{\phantom{A}^{{}^{.}}}}[/math].


Таким образом, множество состояний памяти [math]\Sigma[/math], снабженное отношением порядка [math]\leqslant[/math], является индуктивным упорядоченным множеством.


С учетом результатов, полученных в 4.5 (см. теорему 4.11), отсюда следует, что и множество преобразователей состояний [math](\Sigma\to\Sigma)[/math] есть индуктивное упорядоченное множество. В этом множестве отношение порядка [math]\leqslant[/math] определяется условием


[math]f\leqslant g\quad \Leftrightarrow\quad (\forall\sigma\in\Sigma)(f(\sigma)\leqslant g(\sigma)),[/math]

наименьшим элементом является стирающий преобразователь [math]\bold{0}[/math], такой, что [math]\bold{0}(\sigma)=\mathbb{O}[/math] для всякого [math]\sigma\in\Sigma[/math], а точной верхней гранью неубывающей последовательности преобразователей состояний [math]f_1\leqslant f_2\leqslant \ldots\leqslant f_n\leqslant\ldots[/math] является преобразователь [math]f_0[/math], определяемый следующим образом:


[math](\forall\sigma\in\Sigma)(\forall x\in I)\bigl(f_0(\sigma)(x)= f_n(\sigma)(x)~ \Leftrightarrow~ x\in D(f_n(\sigma))\bigr)[/math], причем [math]D(f_0(\sigma))= \bigcup\limits_{n\geqslant1} D(f_n(\sigma))[/math].

Более того, оказывается, что композиция преобразователей состояний (как отображений) непрерывна в смысле сохранения точных верхних граней (см. 1.8), точнее, для любой неубывающей последовательности преобразователей состояний [math]f_1\leqslant f_2\leqslant \ldots\leqslant f_n\leqslant\ldots[/math] и произвольного преобразователя состояний [math]g[/math] имеем


[math]g\circ\sup f_n=\sup(g\circ f_n),\qquad \sup f_n\circ g=\sup(f_n\circ g).[/math]

Докажем первое из этих равенств. Для произвольного [math]\sigma\in\Sigma[/math] имеем [math]g\circ\sup f_n(\sigma)=\sup f_n(g(\sigma))[/math]. Тогда для всякого [math]x\in D(g\circ f_n(\sigma))[/math] имеем


[math]g\circ\sup f_n(\sigma)(x)= \sup f_n(g(\sigma))(x)= f_n(g(\sigma))(x)= g\circ f_n(\sigma)(x),[/math]

т.е. поскольку, как можно показать, композиция монотонна в смысле определения, данного ранее, то


[math]D(g\circ\sup f_n(\sigma))= \bigcup\limits_{n\geqslant1}D(g\circ f_n)(\sigma)[/math] и [math]g\circ\sup f_n=\sup(g\circ f_n)[/math].

Имея в виду все рассмотренные выше свойства множества [math](\Sigma\to\Sigma)[/math], определим денотационную семантику языка MILAN.


Семантическая функция есть отображение [math][\kern-0.15em[\,\circ\,]\kern-0.15em][/math] множества фраз в множество [math](\Sigma\to\Sigma)[/math] преобразователей состояний памяти.


1. Семантика оператора присваивания:


[math][\kern-0.15em[x^=t]\kern-0.15em](\sigma)(y)=\begin{cases}\sigma(y),&\text{if}\quad y\ne x;\\ t^{\sigma},&\text{if}\quad y=x.\end{cases}[/math]

где через [math]t^{\sigma}[/math] обозначено значение терма [math]t[/math] в состоянии [math]\sigma[/math], равное [math]\mathbb{O}[/math], если хотя бы для одного переменного, входящего в терм, его значение не определено, и равное значению терма при подстановке на место каждого его переменного [math]x[/math] его значения [math]\sigma(x)[/math].


Суть записанного выше семантического правила очень проста: оператору присваивания [math]x:=t[/math] сопоставляется преобразователь состояний, меняющий состояние таким образом, что все переменные, кроме [math]x[/math], сохраняют свои значения, а новое значение переменного [math]x[/math] есть значение правой части оператора присваивания (терма [math]t[/math]) в состоянии [math]\sigma[/math].


2. Семантика оператора условного перехода:


[math]\bigl[\kern-0.15em\bigl[\text{if}~ p(t_1,\ldots,t_n)~ \text{then}~ S_1~\text{else}~ S_2\bigr]\kern-0.15em\bigr]= \begin{cases}[\kern-0.15em[S_1]\kern-0.15em](\sigma),&\text{if}\quad p(t_1^{\sigma},\ldots, t_n^{\sigma})=1;\\ [\kern-0.15em[S_2]\kern-0.15em](\sigma),&\text{if}\quad p(t_1^{\sigma},\ldots, t_n^{\sigma})=0. \end{cases}[/math]

Это правило написано в предположении, что значения всех термов в состоянии [math]\sigma[/math] определены. В противном случае оператору условного перехода сопоставляется стирающий преобразователь [math]\bold{0}[/math]. Подобное же соглашение принимается и далее в аналогичных ситуациях.


Семантика условного перехода без e/se-альтернативы записывается аналогично, но при условии ложности предиката [math]p[/math] в состоянии [math]\sigma[/math] берется тождественный преобразователь состояний [math]ID[/math].


3. Семантика цикла:


[math]\bigl[\kern-0.15em\bigl[\text{while}~ p(t_1,\ldots,t_n)~ \text{do}~ S~ \text{end}\bigr]\kern-0.15em\bigr](\sigma)= \begin{cases}[\kern-0.15em[S]\kern-0.15em]\circ [\kern-0.15em[\text{while}~ p(t_1,\ldots,t_n)~ \text{do}~ S~ \text{end}]\kern-0.15em] (\sigma),&\text{if}\quad p(t_1^{\sigma},\ldots, t_n^{\sigma})=1;\\ ID(\sigma),&\text{if}\quad p(t_1^{\sigma},\ldots, t_n^{\sigma})=0. \end{cases}[/math]

Таким образом, семантика цикла определяется как решение уравнения. Это определение корректно, так как правая часть уравнения есть непрерывное отображение множества [math](\Sigma\to \Sigma)[/math] в себя (что следует из доказанной выше непрерывности композиции преобразователей состояний и очевидной непрерывности тождественного отображения).


4. Семантика последовательности операторов: [math][\kern-0.15em[S_1;S_2]\kern-0.15em]= [\kern-0.15em[S_1]\kern-0.15em]\circ [\kern-0.15em[S_2]\kern-0.15em].[/math].


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


Часовой пояс: UTC + 4 часа [ Летнее время ]


Яндекс.Метрика

Copyright © 2010-2016 MathHelpPlanet.com. All rights reserved