From b2b6003a8feec30490bf77daa2519afec187e438 Mon Sep 17 00:00:00 2001 From: Galin Simeonov Date: Mon, 27 Sep 2021 22:53:48 +0300 Subject: added an english specification --- doc/bulgarian/.project.mg.swp | Bin 0 -> 16384 bytes doc/bulgarian/makefile | 3 + doc/bulgarian/project.mg | 321 ++++++++++++++++++++++++++++++++++++++++++ doc/en.txt | 84 +++++++++++ doc/makefile | 3 - doc/project.mg | 321 ------------------------------------------ 6 files changed, 408 insertions(+), 324 deletions(-) create mode 100644 doc/bulgarian/.project.mg.swp create mode 100644 doc/bulgarian/makefile create mode 100644 doc/bulgarian/project.mg create mode 100644 doc/en.txt delete mode 100644 doc/makefile delete mode 100644 doc/project.mg diff --git a/doc/bulgarian/.project.mg.swp b/doc/bulgarian/.project.mg.swp new file mode 100644 index 0000000..f512973 Binary files /dev/null and b/doc/bulgarian/.project.mg.swp differ diff --git a/doc/bulgarian/makefile b/doc/bulgarian/makefile new file mode 100644 index 0000000..9ca1185 --- /dev/null +++ b/doc/bulgarian/makefile @@ -0,0 +1,3 @@ +install: + cat project.mg | preconv | groff -mg -Tps > a.ps + ps2pdf a.ps a.pdf diff --git a/doc/bulgarian/project.mg b/doc/bulgarian/project.mg new file mode 100644 index 0000000..013fb5c --- /dev/null +++ b/doc/bulgarian/project.mg @@ -0,0 +1,321 @@ +.ps +1 +.vs +1 +.start +.ds C \f[B]C\f[] +.title "Проект по компютърни системи за управление на роботи" +.title "Език за улесняване на програмиране на вградени устройства" +.author "Галин Симеонов Ф.Н. 81635" "gtsimeonov@uni-sofia.bg" +.heading "Увод" +.paragraph +При програмирането на вградени устройства, +някои от проблемите се моделират чрез автомати. +Също е практика да се програмира на езици от ниско ниво, като \*[C], +при които ръчното имплементиране на автомати с каквито и да е размери +често е неинтуитивно, предразполагащо към грешки и трудоемко. +С цел да помогна разработването на програми, чийто модел е ориентиран околу +състоянията на системата, предлагам и имплементирам експериментален миниатюрен език транспилиращ до \*[C]. +.paragraph +За цели имам той да е прост, интуитивен и евентуално лесен за генериране от инстурменти с графичен интернфейс +.footnote +Макар, че директното генериране на код без този език да действа като посредник би било по-смислено. +.footnote end +\&. +.heading "Описание на езика" +.heading "Общ поглед" 2 +Една 'програма' съдържа един или повече 'машини', които действат като контейнери за състояния,събития и преходи. +Всяка машина си има име и има отделно пространство за имена на състояния и събития. +Чрез преходите може да се извикват външни функции. +Ето най-простият пример за това как изглежда кодът: + +.code +machine light_bulb +[ + states [ ON , OFF ]; + events [ TURN_ON , TURN_OFF , SWITCH_STATE ]; + starting on OFF; + transitions + [ + from ON to OFF on event TURN_OFF; + from ON to OFF on event SWITCH_STATE; + + from OFF to ON on event TURN_ON; + from OFF to ON on event TURN_ON; + ]; + +]; +.code end + +След транспилация се генерират 3 файла - xxx.h xxx.c и xxx_external.h, който съответно съдържат +декларациите на служебните функции, тяхната имплементация и декларациите на външните функции, които са използвани от някой преход. +Подаването на събития към тези 'автомати' става посредством служебната функция - \f[B]push_event_to_machine\f[] + +Горният пример не е много функционален, защото комуникацията е само в една посока. +За да може да връща информация и да има функционалност, на всеки преход може да се сложат функции, които да бъдат изпълнени преди преходът да е завършил +.footnote +Това свойство е важно и авторът се е стремил да го запази. Това позволява, например, да се подават събития от функции изпълнени по време на преход +.footnote end +\&. +Taка горният пример може да бъде преработен да вика функция, която действително да включва и изключва някаква лампа: + +.code +machine light_bulb +[ + states [ ON , OFF ]; + events [ TURN_ON , TURN_OFF , SWITCH_STATE ]; + starting on OFF; + transitions + [ + from ON to OFF on event TURN_OFF + execute light "off"; + from ON to OFF on event SWITCH_STATE + execute light "off"; + + from OFF to ON on event TURN_ON + execute light "on"; + from OFF to ON on event TURN_ON + execute light "on"; + ]; + +]; +.code end + +Тук също е демонстрирано как се подават аргументи към тези функции. +Символните низове са избрани като единствен начин да се подават аргументи, защото е предвидено да се транспилира до езици, различни от \*[C], +а въвеждането на типова система или нещо, което да описва различните аргументи би натоварило езикът твърде много и би донесло само минимална печалба. +.paragraph +Възможно е да има повече от една 'машина' в кодът. Например, нека към горния пример добавим: + +.code +machine light_controler +[ + states [ STATIC , BLINKING ]; + events [ SIGNAL , GO_STATIC, START_BLINKING ]; + starting on STATIC; + transitions + [ + from STATIC to BLINKING on event START_BLINKING; + from BLINKING to STATIC on event GO_STATIC; + + from BLINKING to BLINKING on event SIGNAL + execute prod_light_bulb; + + ]; + +]; + +machine timer +[ + states [ ON , OFF ]; + events [ TICK , START , STOP ]; + starting on OFF; + transitions + [ + from ON to OFF on event STOP; + from OFF to ON on event START + execute prod_timer; + from ON to ON on event TICK + execute prod_timer | prod_light_controler; + ]; + +]; +.code end + +Тук може да се види и 'навързване' на различни функции. +timer 'машината' праща сигнал до себе си и до light_controler, а light_controler праща сигнал до light_bulb. +Тук можем да прескочим предаването на събития между 'машините' чрез използването на \f[B]if\f[]. +Променяме третия преход от timer: + +.code + from ON to ON on event TICK + if(light_controler.BLINKING) + execute prod_timer | prod_light_bulb; + +.code end + +Това е условно изпълнение на командите, преходът се случва и състоянието е променено независимо от истинността на условието. +За реализацията на условен преход, в езикът има \f[B]granted\f[] ключовата дума. +Горното може да се опитаме да имплементираме по следния начин: + +.code + from ON to ON on event TICK granted (light_controler.BLINKING) + execute prod_timer | prod_light_bulb; +.code end + +Тук има проблема, че timer спира да работи ако light_controler не е в състояние BLINKING, +защото преходът няма да се случи и \f[B]execute prod_timer\f[] няма да се изпълни. +.footnote +Това, че този пример може да бъде имплементиран на \*[C] под 10 реда, е забелязано от автора. +.footnote end +.paragraph +\f[B]prod_timer\f[],\f[B]prod_light_bulb\f[],\f[B]prod_timer\f[] и \f[B]light\f[] са функции, чиято имплементация трябва да бъде предоставена от програмиста. +Всички външни функции се събират и се записват в генерирания xxxx_exter.h файл. Този пример би генерирал: + +.code +#ifndef XXXX_EXTERN_H +#define XXXX_EXTERN_H XXXX_EXTERN_H + +extern machine_buffer_t* light(machine_buffer_t *arguments,machine_buffer_t *input); +extern machine_buffer_t* prod_light_bulb(machine_buffer_t *arguments,machine_buffer_t *input); +extern machine_buffer_t* prod_light_controler(machine_buffer_t *arguments,machine_buffer_t *input); +extern machine_buffer_t* prod_timer(machine_buffer_t *arguments,machine_buffer_t *input); + +#endif + +.code end + +Ето и една примерна тяхна импелементация заедно с \f[B]main\f[] функцията: + +.code +machine_buffer_t* light(machine_buffer_t *arguments,machine_buffer_t *input) +{ + printf("light %s\n",arguments->buffer); + return NULL; +} +machine_buffer_t* prod_light_bulb(machine_buffer_t *arguments,machine_buffer_t *input) +{ + push_event_to_machine(light_bulb,light_bulb_EVENT_SWITCH_STATE,NULL); + return NULL; +} +machine_buffer_t* prod_light_controler(machine_buffer_t *arguments,machine_buffer_t *input) +{ + push_event_to_machine(light_controler,light_controler_EVENT_SIGNAL,NULL); + return NULL; +} +machine_buffer_t* prod_timer(machine_buffer_t *arguments,machine_buffer_t *input) +{ + push_event_to_machine(timer,timer_EVENT_TICK,NULL); + sleep(1); + return NULL; +} +int main() +{ + push_event_to_machine(light_controler,light_controler_EVENT_START_BLINKING,NULL); + push_event_to_machine(timer,timer_EVENT_START,NULL); + return 0; +} + +.code end +Това ни дава изхода: +.code +light on +light off +light on +light off +light on +light off +light on +light off +light on +\&... +\&... +.code end + +.heading "Формално описание на езика" 2 +Със затъмнените думи и символи обозначавам думи и символи, които трябва да се интерпретират директно. +.heading "Програма" 3 +.right +.nf +програма : машина [ програма ] +.fi +.right end +Програмата е поредица от машини. Всяка машина има уникално име. +.heading "Машина" 3 +.right +.nf +машина : \f[BI]machine\f[] име \f[BI][\f[] вътрешна част на машината \f[BI] ] ; \f[] +вътрешна част на машината : \f[BI]states [\f[] поредица от състояния \f[BI] ] ; \f[] [ вътрешна част на машината ] + \f[BI]events [\f[] поредица от събития \f[BI] ] ; \f[] [ вътрешна част на машината ] + \f[BI]transitions [\f[] поредица от преходи \f[BI] ] ; \f[] [ вътрешна част на машината ] + \f[BI]starting on \f[] име на състояние \f[BI];\f[] [ вътрешна част на машината ] +.fi +.right end + +В една машина може да се срещне само веднъж декларация на състоянията, събитията, преходите и посочване на стартиращо състояние. +Декларацията на стартиращо състояние трябва да е след декларацията на състоянията. То трябва да е сред декларираните състояния. +Декларацията на преходите трябва да е след декларациите на състоянията и на събитията. +Сред декларираните състояния и събития не трябва да има повтарящи се. +Сред преходите не трябва да има две различни, които излизат от едно състояние и имат за етикет едно събитие. +.heading "Преход" 3 +.right +.nf +преход : \f[BI] from \f[] име-на-състояние + \f[BI] to \f[] име-на-състояние \f[BI] on \f[] име-на-събитие [ опашка-на-прехода ] \f[BI];\f[] +опашка-на-прехода : [ \f[BI] granted \f[] израз ] [ условно-изпълнение ] +условно-изпълнение : \f[BI] if \f[] израз условно-изпълнение [ \f[BI] else \f[] условно-изпълнение ] +условно-изпълнение : \f[BI] execute \f[] опашка на изпълнението +опашка-на-изпълнението : име-на-външна-функция \f[BI]"\f[]символен-низ\f[BI]"\f[] [ \f[BI] | \f[] опашка-на-изпълнението ] +.fi +.right end + +Ако изразът след \f[BI]granted\f[] е истина то преходът се реализира и командите в условното изпълнение се изпълняват спрямо семантиката, +иначе преходът не се изпълнява и опашката на преходът не се изпълнява. +Ако изразът след \f[BI]if\f[] е истина то условното изпълнение след изразът се изпълнява, иначе, ако има \f[BI]else\f[] +съответстващ на \f[BI]if\f[]-а то условното узпълнение след \f[BI]else\f[] се изпълнява. +Ако условното изпълнение е от типа започващ с \f[BI]execute\f[] то външните функции се изпълняват в ред на срещане +като изходът на всяка се подава на следващата. Изходът на последната изпълнена функция се изхвърля. +.heading "Израз" 3 +.right +.nf +израз : израз-или +израз-или : израз-и [ \f[BI]|| \f[] израз-или ] +израз-и : израз-не [ \f[BI]&& \f[] израз-и ] +израз-не : [\f[BI]!\f[]]базов-израз +базов-израз : име-на-машина\f[BI].\f[]име-на-състояние | \f[BI](\f[]израз\f[BI])\f[] +.fi +.right end + +Израз може да се оцени до истина или лъжа. +Логическите оператори имат обичайната семантика. +В базовия израз е позволено да се посочват състояния на други машини, но не е позволено да се посочват състояния на машината, +в която се намира изразът. Тези посочвания се оценяват до истина ако посочената машина е заела посоченото състояние. +Могат да се посочват имена на машини, които са декларирани след сегашната, но те трябва да съществуват. Това важи и за състоянията, те трябва също и да принадлежат на посочената машина. + +.heading "Детайли на имплементацията" +За да се реализира обмена на информация между генерирания код и написания, +е дефинирана структура \f[B]machine_buffer_t\f[], в която се записват данните и техният размер. +Генерират се и няколко помощни функции, които улесняват работата с такива структури. +За да се запази свойството - командите на преходът да се изпълнят преди състоянието да се смени, +се използва опашка, в която се записват +.heading "Описание на командните аргументи" +Имплементацията на този език предадена от автора приема следните аргументи. + +.code +--print-tokens +.code end +Извежда разпознатите лексеми +.code +--print-ast +.code end +Извежда разпознатите структури в текста. ( Абстрактното синтактично дърво ) +.code +-o име-на-файл | --output име-на-файл +.code end +Посочва префиксът на генерираните файлове. Например \f[B]xxxx.h xxxx.c xxxx_external.h\f[]. +.code +--extern-mutex +.code end +Добавя мутекс преди и след подаването на събитие. Този мутекс трябва да се имплементира външно. +.code +--extern-queue +.code end +Дава възможност на програмиста да даде собствена имплементация на опашката използвана при задържането на събития. +.code +--extern-buffer +.code end +Дава възможност на програмиста да даде собствена имплементация на структурата използвана за пренос на данни. + +.heading "Забележки" +За имплементацията е използвана само стандартната \*[C] библиотека, което би помогнало този транспилатор да бъде +компилиран до много операционни системи. +.heading "Бъдещи насоки" +.list +.item +Да се добави ключова дума \f[B]signal\f[] която да праща сигнал до определена машина, за да не трябва да го имплементира програмистът. +.item +Да се добави семанитка за състояния и събития, като например - 'при пристигане до това състояние изпълни ... '. +.item +Да се направи така, че отделните машини да могат да бъдат на различни физически устройства, т.е. да бъде направен разпределен. +.item +Да се направи на пълен език за програмиране. +.list end +.finish diff --git a/doc/en.txt b/doc/en.txt new file mode 100644 index 0000000..95f1f91 --- /dev/null +++ b/doc/en.txt @@ -0,0 +1,84 @@ +MEGATRON transpiler for a language describing automatas + +Here is a description of the language + + + +Things encased with "" are to be taken literally, things encased in [] are optional, +things encased with () are grouped and are to be taken as a unit, +things encased in {} can appear zero or more times and things encased in {}+ can appear one +or more times + +Syntax: + := { }+ + + := "[" "]" ";" + + := { ";" | ";" | ";" \ + | "starting" "on" ";" } + + := "states" "[" { [ "on" "entering" ] \ + [ "on" "exiting" ] }+ "]" + + := "events" "[" { }+ "]" + := "transitions" "[" { ";" }+ "]" + := "from" "to" "on" "event" [ ] [ ] ";" + + := + := "if" "(" ")" [ "else" ] + + := "granted" "(" ")" + + := "execute" + := [ ] [ "|" ] + + := "." | "(" ")" + := "!" | + := "&&" + := "||" + := + +Constraints: + The name of each machine id shall be unique in a program. + + The order of the machine declarations do not matter to the constraint checks. + + In the internals of each machine there will be exactly one states definition, events definition, transitions + definition and starting state declaration. + + State ids shall not have duplicates in the same machine they are defined, meaning you could have a state + id appear in two machines. + + Event ids shall not have duplicates across all machines, meaning you can not have an event id appear in + two machines at the same time in the same program. The same goes with machine ids. + + Event ids, machine ids and pipeline ids share a namespace, meaning you can not have an id that is both + a machine id and an event id at the same time or a pipeline id that is a machine id. + + Let a primary expression be in the form "." . The first id shall be a machine id and the second + a state id that belongs to the denoted machine. + + Transition ids shall be state id belonging to the machine the transitions declaration apears in. + + The first id in a transition shall not appear as the first id in another transition in the same + transition definition. Meaning you can not have multiple transitions stemming from the same state. + +Semantics: + A program describes a set of possibly interdependant automata that execute external code upon certain conditions. + + A machine is always in a single state, starting on the starting state. + + The outside environment can pass events to any machine. The machine switches states and executes + external functions. The events are processed in the order they arrive. + + If no transition can take an event, the event is dropped. + A transition of states occurs if there is no granted part to the transition. + If there is a granted part of the transition then the expression in the granted part must evaluate to 1 + otherwise the transition does not occur and the event is dropped. + + If a transition occurs then and only then is the conditional execution of external functions executed. + Meaning that the if does not go off if the granted statement fails. + + A primary expression in the form "." evaluates to 1 if the machine with the first id + is currently in the state with the second id, otherwise it evaluates to 0. For example M.a is 1 + if the machine 'M' is in the state 'a'. diff --git a/doc/makefile b/doc/makefile deleted file mode 100644 index 9ca1185..0000000 --- a/doc/makefile +++ /dev/null @@ -1,3 +0,0 @@ -install: - cat project.mg | preconv | groff -mg -Tps > a.ps - ps2pdf a.ps a.pdf diff --git a/doc/project.mg b/doc/project.mg deleted file mode 100644 index 013fb5c..0000000 --- a/doc/project.mg +++ /dev/null @@ -1,321 +0,0 @@ -.ps +1 -.vs +1 -.start -.ds C \f[B]C\f[] -.title "Проект по компютърни системи за управление на роботи" -.title "Език за улесняване на програмиране на вградени устройства" -.author "Галин Симеонов Ф.Н. 81635" "gtsimeonov@uni-sofia.bg" -.heading "Увод" -.paragraph -При програмирането на вградени устройства, -някои от проблемите се моделират чрез автомати. -Също е практика да се програмира на езици от ниско ниво, като \*[C], -при които ръчното имплементиране на автомати с каквито и да е размери -често е неинтуитивно, предразполагащо към грешки и трудоемко. -С цел да помогна разработването на програми, чийто модел е ориентиран околу -състоянията на системата, предлагам и имплементирам експериментален миниатюрен език транспилиращ до \*[C]. -.paragraph -За цели имам той да е прост, интуитивен и евентуално лесен за генериране от инстурменти с графичен интернфейс -.footnote -Макар, че директното генериране на код без този език да действа като посредник би било по-смислено. -.footnote end -\&. -.heading "Описание на езика" -.heading "Общ поглед" 2 -Една 'програма' съдържа един или повече 'машини', които действат като контейнери за състояния,събития и преходи. -Всяка машина си има име и има отделно пространство за имена на състояния и събития. -Чрез преходите може да се извикват външни функции. -Ето най-простият пример за това как изглежда кодът: - -.code -machine light_bulb -[ - states [ ON , OFF ]; - events [ TURN_ON , TURN_OFF , SWITCH_STATE ]; - starting on OFF; - transitions - [ - from ON to OFF on event TURN_OFF; - from ON to OFF on event SWITCH_STATE; - - from OFF to ON on event TURN_ON; - from OFF to ON on event TURN_ON; - ]; - -]; -.code end - -След транспилация се генерират 3 файла - xxx.h xxx.c и xxx_external.h, който съответно съдържат -декларациите на служебните функции, тяхната имплементация и декларациите на външните функции, които са използвани от някой преход. -Подаването на събития към тези 'автомати' става посредством служебната функция - \f[B]push_event_to_machine\f[] - -Горният пример не е много функционален, защото комуникацията е само в една посока. -За да може да връща информация и да има функционалност, на всеки преход може да се сложат функции, които да бъдат изпълнени преди преходът да е завършил -.footnote -Това свойство е важно и авторът се е стремил да го запази. Това позволява, например, да се подават събития от функции изпълнени по време на преход -.footnote end -\&. -Taка горният пример може да бъде преработен да вика функция, която действително да включва и изключва някаква лампа: - -.code -machine light_bulb -[ - states [ ON , OFF ]; - events [ TURN_ON , TURN_OFF , SWITCH_STATE ]; - starting on OFF; - transitions - [ - from ON to OFF on event TURN_OFF - execute light "off"; - from ON to OFF on event SWITCH_STATE - execute light "off"; - - from OFF to ON on event TURN_ON - execute light "on"; - from OFF to ON on event TURN_ON - execute light "on"; - ]; - -]; -.code end - -Тук също е демонстрирано как се подават аргументи към тези функции. -Символните низове са избрани като единствен начин да се подават аргументи, защото е предвидено да се транспилира до езици, различни от \*[C], -а въвеждането на типова система или нещо, което да описва различните аргументи би натоварило езикът твърде много и би донесло само минимална печалба. -.paragraph -Възможно е да има повече от една 'машина' в кодът. Например, нека към горния пример добавим: - -.code -machine light_controler -[ - states [ STATIC , BLINKING ]; - events [ SIGNAL , GO_STATIC, START_BLINKING ]; - starting on STATIC; - transitions - [ - from STATIC to BLINKING on event START_BLINKING; - from BLINKING to STATIC on event GO_STATIC; - - from BLINKING to BLINKING on event SIGNAL - execute prod_light_bulb; - - ]; - -]; - -machine timer -[ - states [ ON , OFF ]; - events [ TICK , START , STOP ]; - starting on OFF; - transitions - [ - from ON to OFF on event STOP; - from OFF to ON on event START - execute prod_timer; - from ON to ON on event TICK - execute prod_timer | prod_light_controler; - ]; - -]; -.code end - -Тук може да се види и 'навързване' на различни функции. -timer 'машината' праща сигнал до себе си и до light_controler, а light_controler праща сигнал до light_bulb. -Тук можем да прескочим предаването на събития между 'машините' чрез използването на \f[B]if\f[]. -Променяме третия преход от timer: - -.code - from ON to ON on event TICK - if(light_controler.BLINKING) - execute prod_timer | prod_light_bulb; - -.code end - -Това е условно изпълнение на командите, преходът се случва и състоянието е променено независимо от истинността на условието. -За реализацията на условен преход, в езикът има \f[B]granted\f[] ключовата дума. -Горното може да се опитаме да имплементираме по следния начин: - -.code - from ON to ON on event TICK granted (light_controler.BLINKING) - execute prod_timer | prod_light_bulb; -.code end - -Тук има проблема, че timer спира да работи ако light_controler не е в състояние BLINKING, -защото преходът няма да се случи и \f[B]execute prod_timer\f[] няма да се изпълни. -.footnote -Това, че този пример може да бъде имплементиран на \*[C] под 10 реда, е забелязано от автора. -.footnote end -.paragraph -\f[B]prod_timer\f[],\f[B]prod_light_bulb\f[],\f[B]prod_timer\f[] и \f[B]light\f[] са функции, чиято имплементация трябва да бъде предоставена от програмиста. -Всички външни функции се събират и се записват в генерирания xxxx_exter.h файл. Този пример би генерирал: - -.code -#ifndef XXXX_EXTERN_H -#define XXXX_EXTERN_H XXXX_EXTERN_H - -extern machine_buffer_t* light(machine_buffer_t *arguments,machine_buffer_t *input); -extern machine_buffer_t* prod_light_bulb(machine_buffer_t *arguments,machine_buffer_t *input); -extern machine_buffer_t* prod_light_controler(machine_buffer_t *arguments,machine_buffer_t *input); -extern machine_buffer_t* prod_timer(machine_buffer_t *arguments,machine_buffer_t *input); - -#endif - -.code end - -Ето и една примерна тяхна импелементация заедно с \f[B]main\f[] функцията: - -.code -machine_buffer_t* light(machine_buffer_t *arguments,machine_buffer_t *input) -{ - printf("light %s\n",arguments->buffer); - return NULL; -} -machine_buffer_t* prod_light_bulb(machine_buffer_t *arguments,machine_buffer_t *input) -{ - push_event_to_machine(light_bulb,light_bulb_EVENT_SWITCH_STATE,NULL); - return NULL; -} -machine_buffer_t* prod_light_controler(machine_buffer_t *arguments,machine_buffer_t *input) -{ - push_event_to_machine(light_controler,light_controler_EVENT_SIGNAL,NULL); - return NULL; -} -machine_buffer_t* prod_timer(machine_buffer_t *arguments,machine_buffer_t *input) -{ - push_event_to_machine(timer,timer_EVENT_TICK,NULL); - sleep(1); - return NULL; -} -int main() -{ - push_event_to_machine(light_controler,light_controler_EVENT_START_BLINKING,NULL); - push_event_to_machine(timer,timer_EVENT_START,NULL); - return 0; -} - -.code end -Това ни дава изхода: -.code -light on -light off -light on -light off -light on -light off -light on -light off -light on -\&... -\&... -.code end - -.heading "Формално описание на езика" 2 -Със затъмнените думи и символи обозначавам думи и символи, които трябва да се интерпретират директно. -.heading "Програма" 3 -.right -.nf -програма : машина [ програма ] -.fi -.right end -Програмата е поредица от машини. Всяка машина има уникално име. -.heading "Машина" 3 -.right -.nf -машина : \f[BI]machine\f[] име \f[BI][\f[] вътрешна част на машината \f[BI] ] ; \f[] -вътрешна част на машината : \f[BI]states [\f[] поредица от състояния \f[BI] ] ; \f[] [ вътрешна част на машината ] - \f[BI]events [\f[] поредица от събития \f[BI] ] ; \f[] [ вътрешна част на машината ] - \f[BI]transitions [\f[] поредица от преходи \f[BI] ] ; \f[] [ вътрешна част на машината ] - \f[BI]starting on \f[] име на състояние \f[BI];\f[] [ вътрешна част на машината ] -.fi -.right end - -В една машина може да се срещне само веднъж декларация на състоянията, събитията, преходите и посочване на стартиращо състояние. -Декларацията на стартиращо състояние трябва да е след декларацията на състоянията. То трябва да е сред декларираните състояния. -Декларацията на преходите трябва да е след декларациите на състоянията и на събитията. -Сред декларираните състояния и събития не трябва да има повтарящи се. -Сред преходите не трябва да има две различни, които излизат от едно състояние и имат за етикет едно събитие. -.heading "Преход" 3 -.right -.nf -преход : \f[BI] from \f[] име-на-състояние - \f[BI] to \f[] име-на-състояние \f[BI] on \f[] име-на-събитие [ опашка-на-прехода ] \f[BI];\f[] -опашка-на-прехода : [ \f[BI] granted \f[] израз ] [ условно-изпълнение ] -условно-изпълнение : \f[BI] if \f[] израз условно-изпълнение [ \f[BI] else \f[] условно-изпълнение ] -условно-изпълнение : \f[BI] execute \f[] опашка на изпълнението -опашка-на-изпълнението : име-на-външна-функция \f[BI]"\f[]символен-низ\f[BI]"\f[] [ \f[BI] | \f[] опашка-на-изпълнението ] -.fi -.right end - -Ако изразът след \f[BI]granted\f[] е истина то преходът се реализира и командите в условното изпълнение се изпълняват спрямо семантиката, -иначе преходът не се изпълнява и опашката на преходът не се изпълнява. -Ако изразът след \f[BI]if\f[] е истина то условното изпълнение след изразът се изпълнява, иначе, ако има \f[BI]else\f[] -съответстващ на \f[BI]if\f[]-а то условното узпълнение след \f[BI]else\f[] се изпълнява. -Ако условното изпълнение е от типа започващ с \f[BI]execute\f[] то външните функции се изпълняват в ред на срещане -като изходът на всяка се подава на следващата. Изходът на последната изпълнена функция се изхвърля. -.heading "Израз" 3 -.right -.nf -израз : израз-или -израз-или : израз-и [ \f[BI]|| \f[] израз-или ] -израз-и : израз-не [ \f[BI]&& \f[] израз-и ] -израз-не : [\f[BI]!\f[]]базов-израз -базов-израз : име-на-машина\f[BI].\f[]име-на-състояние | \f[BI](\f[]израз\f[BI])\f[] -.fi -.right end - -Израз може да се оцени до истина или лъжа. -Логическите оператори имат обичайната семантика. -В базовия израз е позволено да се посочват състояния на други машини, но не е позволено да се посочват състояния на машината, -в която се намира изразът. Тези посочвания се оценяват до истина ако посочената машина е заела посоченото състояние. -Могат да се посочват имена на машини, които са декларирани след сегашната, но те трябва да съществуват. Това важи и за състоянията, те трябва също и да принадлежат на посочената машина. - -.heading "Детайли на имплементацията" -За да се реализира обмена на информация между генерирания код и написания, -е дефинирана структура \f[B]machine_buffer_t\f[], в която се записват данните и техният размер. -Генерират се и няколко помощни функции, които улесняват работата с такива структури. -За да се запази свойството - командите на преходът да се изпълнят преди състоянието да се смени, -се използва опашка, в която се записват -.heading "Описание на командните аргументи" -Имплементацията на този език предадена от автора приема следните аргументи. - -.code ---print-tokens -.code end -Извежда разпознатите лексеми -.code ---print-ast -.code end -Извежда разпознатите структури в текста. ( Абстрактното синтактично дърво ) -.code --o име-на-файл | --output име-на-файл -.code end -Посочва префиксът на генерираните файлове. Например \f[B]xxxx.h xxxx.c xxxx_external.h\f[]. -.code ---extern-mutex -.code end -Добавя мутекс преди и след подаването на събитие. Този мутекс трябва да се имплементира външно. -.code ---extern-queue -.code end -Дава възможност на програмиста да даде собствена имплементация на опашката използвана при задържането на събития. -.code ---extern-buffer -.code end -Дава възможност на програмиста да даде собствена имплементация на структурата използвана за пренос на данни. - -.heading "Забележки" -За имплементацията е използвана само стандартната \*[C] библиотека, което би помогнало този транспилатор да бъде -компилиран до много операционни системи. -.heading "Бъдещи насоки" -.list -.item -Да се добави ключова дума \f[B]signal\f[] която да праща сигнал до определена машина, за да не трябва да го имплементира програмистът. -.item -Да се добави семанитка за състояния и събития, като например - 'при пристигане до това състояние изпълни ... '. -.item -Да се направи така, че отделните машини да могат да бъдат на различни физически устройства, т.е. да бъде направен разпределен. -.item -Да се направи на пълен език за програмиране. -.list end -.finish -- cgit v1.2.3