
- •2.3 Розвиток основних понять програмування 53
- •1. Формалізація простої мови програмування
- •1.1 Неформальний опис простої мови програмування
- •1.2 Формальний опис синтаксису мови sipl
- •Малюнок 1.1. Дерево синтаксичного виводу програми gcd
- •1.3 Формальний опис семантики мови sipl
- •Малюнок 1.3. Алгебра даних мови sipl
- •1.3.2 Функції
- •1.3.3 Композиції
- •1.3.4 Програмні алгебри
- •Малюнок 1.4. Алгебра функцій (програмна алгебра)
- •1.3.5 Визначення семантичних термів
- •1.3.6 Побудова семантичного терму програми
- •1.3.7 Обчислення значень семантичних термів
- •1.3.8 Загальна схема формалізації мови sipl
- •Малюнок 1.5 Схема визначення композиційної семантики
- •1.4 Властивості програмної алгебри
- •2. Розвиток основних понять програмування
- •2.1 Аналіз словникових визначень поняття програми
- •2.2 Розвиток поняття програми з гносеологічної точки зору
- •2.3 Розвиток основних понять програмування
- •2.3.1 Початкова тріада понять програмування
- •Малюнок 2.2. Сфера інформатизації як особлива сфера суспільства
- •Малюнок 2.3. Тріада цільового призначення програм
- •2.3.2 Тріада прагматичності програм
- •Малюнок 2.4. Тріада прагматичності програм
- •2.3.3 Тріада основних понять програмування
- •Малюнок 2.5. Тріада основних понять програмування
- •2.3.4 Пентада основних понять програмування
- •Малюнок 2.6. Пентада основних понять програмування
- •2.4 Розвиток основних програмних понять
- •2.4.1 Тріада основних програмних понять
- •Малюнок 2.7. Програма як діалектичне заперечення проблеми
- •2.4.2 Пентада основних програмних понять
- •2.5 Сутнісні та семіотичні аспекти програм
- •2.6 Програми і мови
- •2.7 Пентада програмних понять процесного типу
- •3. Формалізація програмних понять
- •3.1 Теоретико-функціональна формалізація
- •3.2 Класи функцій
- •3.3 Програмні системи
- •3.4 Рівні конкретизації програмних систем
- •4. Синтактика: формальні мови та граматики
- •4.1 Розвиток понять формальної мови та породжучої граматики
- •4.2 Визначення основних понять формальних мов
- •4.3 Операції над формальними мовами
- •4.3 Породжуючі граматики
- •4.5 Ієрархія граматик Хомського
- •4.6 Автоматні формалізми сприйняття мов
- •4.6.1 Машини Тьюрінга
- •4.6.2 Еквівалентність машин Тьюрінга та породжуючих граматик
- •4.6.3 Лінійно-обмежені автомати
- •4.6.4 Магазинні автомати
- •4.6.5 Скінченні автомати
- •4.7 Методи подання синтаксису мов програмування
- •4.7.1 Нормальні форми Бекуса–Наура
- •4.7.2 Модифіковані нормальні форми Бекуса–Наура
- •4.7.3 Синтаксичні діаграми
- •4.8 Властивості контекстно-вільних граматик
- •4.8.1 Видалення несуттєвих символів
- •4.8.2 Видалення -правил
- •4.8.3 Нормальна форма Хомського
- •4.8.4 Нормальна форма Грейбах
- •4.8.5 Рекурсивні нетермінали
- •4.9 Властивості контекстно-вільних мов
- •4.10 Операції над формальними мовами
- •4.11 Дерева виводу
- •4.12 Однозначні та неоднозначні граматики
- •4.13 Розв’язні та нерозв’язні проблеми кв-граматик та мов
- •4.14 Рівняння в алгебрах формальних мов
- •5. Теорія рекурсії (теорія найменшої нерухомої точки)
- •5.1 Рекурсивні визначення та рекурсивні рівняння
- •5.2 Частково впорядковані множини, границі ланцюгів та -області
- •5.3 Неперервні відображення
- •5.4 Теореми про нерухомі точки
- •5.5 Конструювання похідних -областей
- •5.6 Властивості оператора найменшої нерухомої точки
- •5.7 Застосування теорії ннт
- •5.7.1 Уточнення синтаксису мов програмування
- •5.7.2 Семантика мов програмування
- •5.7.3 Рекурсивні розширення мови sipl
1.2 Формальний опис синтаксису мови sipl
Для опису синтаксису мов зазвичай використовують БНФ (Форми Бекуса-Наура). Програми (або їх частини) виводяться із метазмінних (нетерміналів), які записуються у кутових дужках. Метазмінні задають синтаксичні класи. В процесі виводу метазмінні замінюються на праві частини правил, що задають ці метазмінні. Праві частини для однієї метазмінної розділяються знаком альтернативи « | ». Процес породження припиняється, якщо всі метазмінні замінено на термінальні символи.
Синтаксис мови SIPL можна задати за допомогою наступної БНФ:
Таблиця 1.2
Ліва частина правила – метазмінна (дефінієндум) |
Права частина правила (дефінієнс) |
Ім’я правила |
<програма> ::= |
begin <оператор> end |
NP1 |
<оператор> ::=
|
<змінна>:=<вираз> | <оператор> ; <оператор>| if <умова> then <оператор> else <оператор> | while <умова> do <оператор> | begin <оператор> end | skip |
NS1 NS2 NS3 NS4 NS5 NS6 |
<вираз> ::= |
<число> | <змінна> | <вираз> + <вираз> | <вираз> – <вираз> | <вираз> * <вираз> | <вираз> ÷ <вираз> | (<вираз>) |
NA1– NA7 |
<умова> ::= |
true | false | <вираз> < <вираз> | <вираз> <вираз> | <вираз> = <вираз> | <вираз> <вираз> | <вираз> > <вираз> | <вираз> <вираз> | <умова> <умова> | <умова> <умова> | <умова> | (<умова>) |
NB1– – NB12 |
<змінна> ::= |
M | N | . . . |
NV1–… |
<число> ::= |
. . . –1 | 0 | 1 | 2 | 3 | . . . |
NN1–… |
Наведена БНФ задає мову SIPL як набір речень (слів), які виводяться з метазмінної <програма>. Точне визначення виводу буде подано пізніше, зараз тільки відмітимо, що вивід можна подати у вигляді дерева.
Щоб переконатись у синтаксичній правильності програми треба побудувати її вивід. Зокрема, для нашої програми GCD маємо наступне дерево виводу.
Малюнок 1.1. Дерево синтаксичного виводу програми gcd
Побудоване дерево синтаксичного виводу дозволяє стверджувати синтаксичну правильність програми GCD. Дійсно, якщо записати зліва направо послідовність усіх термінальних символів, то отримаємо програму GCD, що говорить про її вивідність у БНФ мови SIPL, тобто про її синтаксичну правильність.
Аналізуючи далі наведену БНФ можна відзначити, що вона досить просто описує основні конструкції мови SIPL. Але зворотною стороної цієї простоти є неодзначність цієї БНФ. Наприклад, вираз X+Y*Z має два різних дерева виводу, що ведуть до різних семантик (малюнок 1.2). Тому неоднозначність БНФ значно ускладнює семантичний аналіз програм.
Малюнок 1.2. Дерева синтаксичного виводу виразу X+Y*Z
Однозначності побудови дерева синтаксичного виводу можна досягти введенням пріоритетів операцій та правил асоціативності для операцій одного пріоритету. Слід відзначити, що в математиці при описі пріоритетів, як правило, не розрізняють синтаксичний і семантичний аспекти, тому часто говорять, що пріоритети задають порядок виконання операцій (семантичний аспект), замість того, щоб говорити про порядок структурного аналізу виразу (синтаксичний аспект). Такий розгляд об’єкту, коли не виокремлюються його різні аспекти та складові, часто називають синкретичним. У випадку мови SIPL однозначність аналізу може порушуватись при формуванні операндів операцій (синтаксичних конструкторів) різного типу. Будемо виокремлювати три типи операцій:
-
арифметичні (бінарні операції +, –, *, ) ,
-
бульові (бінарні операції порівняння <, , =, , , >, бінарні операції диз’юнкції та кон’юнкції та унарна операція заперечення ),
-
операторні (присвоєння, оператори послідовного виконання « _;_ », умовний оператор if_then_else_ та оператор циклу while_do_).
Тут символ підкреслення позначає операнд (або параметр) оператора. Перші дві групи операцій є традиційними, як і їх пріоритети. Третя група потребує певного пояснення. Справа в тому, що наприклад, синтаксична конструкція виду if b then S1 else S2; S3 може аналізуватись по-різному. Одне трактування може відносити до умовного оператора (його else-частини) послідовність операторів S2; S3, інше трактування – тільки один оператор S2. Різні трактування будуть задавати різну семантику. Те саме стосується і конструкцій виду while b do S1; S2 та S1; S2; S3. На семантику також впливає порядок застосування операцій одного типу. Так, вираз a1–a2–a3 можна аналізувати зліва-направо (лівоасоціативно), що можна подати як (a1–a2)–a3, так і справа-наліво (правоасоціативно), що можна подати як a1–(a2–a3) (=(a1–a2)+a3). Щоб подолати неоднозначність синтаксичного аналізу будемо вважати, що всі бінарні операції лівоасоціативні (обчислюються зліва-направо) та що пріоритет операцій наступний (у порядку зменшення):
-
множення * та ділення ,
-
додавання + та віднімання –,
-
операції порівняння <, , =, , , >,
-
заперечення ,
-
кон’юнкція ,
-
диз’юнкція ,
-
умовний оператор if_then_else_ та оператор циклу while_do_,
-
послідовне виконання « ; » .
Зауважимо ще раз, що однозначність синтаксичного аналізу не зовсім адекватно подається пріоритетами операцій, які мають семантичну природу. Тому можливі розбіжності між цими поняттями.
Є і друга можливість досягти однозначності БНФ мови SIPL – ввести нові метасимволи та нові правила їх визначення. Пропонуємо читачам зробити це самостійно.
Наведені вище позначення метазмінних не зовсім зручні, тому часто використовують форми більш близькі до математики. А саме, введемо позначення для всіх синтаксичних категорій та нові метазмінні, що вказують на представників цих категорій.
Таблиця 1.3
Метазмінна |
Синтаксична категорія |
Нова метазмінна |
<програма> |
Prog |
P |
<оператор> |
Stm |
S |
<вираз> |
Aexp |
a |
<умова> |
Bexp |
b |
<змінна> |
Var |
x |
<число> |
Num |
n |
В наведених позначеннях БНФ мови SIPL набуває наступного вигляду:
Таблиця 1.4
Ліва частина правила – метазмінна |
Права частина правила |
Ім’я правила |
P::= |
begin S end |
P1 |
S::=
|
x:=a | S1 ; S2| if b then S1 else S2 | while b do S | begin S end | skip |
S1–S6 |
a::= |
n | x | a1 + a2 | a1 – a2 | a1 * a2 | a1 ÷ a2 | (a) |
A1– A7 |
b::= |
true | false | a1<a2 | a1 a2 | a1= a2 | a1a2 | a1>a2 | a1 a2 | b1b2 | b1 b2 | b | (b) |
B1 – B12 |
x::= |
M | N | . . . |
NV1–… |
n::= |
. . . –1 | 0 | 1 | 2 | 3 | . . . |
NN1–… |
Надалі будемо користуватися введеними позначеннями для запису структури програм та їх складових.
Дотепер ми користувались інтуїтивним розумінням БНФ. Разом з тим слід розуміти, що можуть існувати різні уточнення БНФ (про це буде мова в розділі з синтактики). Зараз приймемо, що БНФ дозволяє прописати індуктивне визначення синтаксичних категорій. Дійсно, наведена БНФ визначає шість синтаксичних категорій (класів): Num, Var, Aexp, Bexp, Stm, Prog. Вони можуть бути задані наступним індуктивним визначенням.
1. База індукції:
-
Num={…, -1, 0, 1, 2, 3, …},
-
Var={X, Y, …},
-
якщо nNum, то nAexp,
-
якщо xVar, то xAexp,
-
true, false належать Bexp,
-
skip належить Stm.
2. Крок індукції:
-
якщо a, a1, a2Aexp, то записи (вирази)
-
a1 + a2,
-
a1 – a2,
-
a1 * a2,
-
a1 ÷ a2,
-
(a)
належать Aexp,
-
якщо a1, a2Aexp, b , b1, b2Bexp, то записи (умови)
-
a1<a2,
-
a1a2,
-
a1=a2,
-
a1a2,
-
a1>a2,
-
a1a2,
-
b1b2,
-
b1b2,
-
b,
-
(b)
належать Bexp,
-
якщо xVar, aAexp, bBexp, S, S1, S2Stm, то записи (оператори)
-
x:=a,
-
S1 ; S2,
-
if b then S1 else S2,
-
while b do S,
-
begin S end
належать Stm,
-
якщо SStm, то запис begin S end належить Prog.
На підставі такого індуктивного визначення може бути задане визначення синтаксичних категорій за допомогою рекурентних співвідношень. Пропонуємо читачам зробити це самостійно.
Таким чином, можна стверджувати, що наведеними визначеннями синтаксис мови SIPL задато точно (формально).
Перейдемо тепер до визначення семантики мови SIPL.