Санкт-Петербургский государственный университет
Опубликован: 04.12.2007 | Доступ: свободный | Студентов: 2432 / 255 | Оценка: 4.30 / 3.65 | Длительность: 16:28:00
ISBN: 978-5-94774-823-9
Лекция 12:

Пример предметно-ориентированного визуального языка

< Лекция 11 || Лекция 12: 1234 || Лекция 13 >
Аннотация: В этой лекции рассматривается пример предметно-ориентированного визуального языка для моделирования компонент и их конечно-автоматного поведения. На этом примере демонстрируются различные формальные техники, используемые для спецификации визуальных языков - грамматики в форме Бэкуса-Наура, графические грамматики, метамоделирование, язык OCL, XML. Сформулированы практические рекомендации по созданию метамоделей для DSL
Ключевые слова: DSL, компонент, конечные, component, language, список, server, монитор, параметр, сервер, client, ПО, запрос, информация, end, синтаксис, прагматика, грамматики в форме Бэкуса-Наура, грамматика, определение, model, головная конструкция, идентификатор, терминал, нетерминал, ASCI, произвольное, конечный автомат, ссылка, ref, очередь, входной, фигурные скобки, аргумент, операции, посылка сигнала, метамоделирование, диаграммы классов, tools, ссылочная целостность, метамодель, значение, целостность, агрегирование, операторы, класс, параметр компонента, контекст, ключевое слово, слово, функция, квантор всеобщности, транслятор, графические грамматики, бинарный оператор, постфиксный оператор, диаграмма, автомат, усложним пример, служебный синтаксис, xml-схема, XML-документ, XML, schema, тег, тег-тип, тег-значение, атрибут, string, наследование, исполняемая семантика, алгоритм, визуальное моделирование, нотация, команда, предметно-ориентированый язык, специалист предметной области, предметной области, ассоциация, DSM, понятность

Пример визуального языка

В предыдущих лекциях уже были рассмотрены некоторые визуальные языки - UML и BPMN. Однако они слишком большие и сложные, чтобы на их примере учиться создавать собственные DSL. Поэтому в этой лекции будет представлен небольшой, "игрушечный" визуальный язык. Он позволяет описать множество компонент с атрибутами и методами, набор сообщений, которыми могут обмениваться экземпляры компонент, а также конечные автоматы, описывающие поведение каждой компоненты. В дальнейшем я буду называть этот язык SCL (Simple Component Language). Пример SCL-модели показан на рис. 12.1.

Пример SCL-модели

Рис. 12.1. Пример SCL-модели

На рис. 12.1, а представлены три компоненты - Client, Server и Monitor, - а также список сигналов, которыми они могут обмениваться. Экземпляры компонент взаимодействуют друг с другом через посылку/прием сигналов из этого списка. В SCL для упрощения у компонент нет интерфейсов, а все сигналы глобальные. Все компоненты их "видят", а значит, могут использовать.

Поведение компонент представляется с помощью конечных автоматов - пример для компоненты Server показан на рис. 12.1, б. Монитор (экземпляр компоненты Monitor) создается автоматически, при запуске всей системы, о чем свидетельствует на рис. 12.1, а первый параметр после его имени, равный единице. Монитор создает экземпляр компоненты Server (далее - сервер) и экземпляр компоненты Client (далее - клиент). Экземпляры этих компонент создаются монитором, а не по умолчанию, при запуске системы. Поэтому первый параметр после имен этих компонент равен нулю. В этой небольшой "игрушечной" системе может существовать не более одного клиента и сервера, на что указывают вторые параметры после имен этих компонент, равные единице.

На рис. 12.1, б представлено поведение сервера. Сервер, после того, как его создаст монитор, оказывается в состоянии Start и вызывает свою процедуру Init(). Эта процедура выполняет все служебные действия по инициализации сервера. Далее он переходит в состояние Idle, в котором готов обслужить запросы клиента. При получении такого запроса (сигнал Request) сервер оповещает клиента с помощью сигнала Respond о том, что запрос до него дошел и требуется дополнительная информация. Клиент посылает либо сигнал Info1, либо сигнал Info2. В зависимости от этого сервер или принимает запрос на обработку, или нет. В первом случае он посылает клиенту сигнал Accept и вызывает свою процедуру-обработчик запроса AcceptHandle(), во втором случае он посылает клиенту сигнал Reject. В обоих случаях сервер переходит в состояние Idle и готов обрабатывать следующие запросы. В этом же состоянии сервер может обработать сигнал монитора Terminate, присылаемый ему при необходимости прекратить работу. В этом случае, для корректного завершения своей работы сервер вызывает процедуру TerminateHandle(). После ее завершения сервер переходит в состояние End и окончательно завершается. Нетрудно продолжить этот пример, дописав конечные автоматы для клиента и монитора.

Наверное, про этот язык понятно все или почти все прямо из приведенного выше примера. Однако так происходит потому, что SCL очень прост. Если в него добавить связи между компонентами, параметры сигналов, ветвления в переходах и т. д., то он бы существенно усложнился и возникла бы потребность в том, чтобы создать его точное описание - определить синтаксис, семантику и прагматику. Это и будет проделано ниже в учебных целях.

Абстрактный синтаксис в форме грамматик Бэкуса-Наура

Здесь не будет дано точных определений формального языка, грамматики, грамматики в форме Бэкуса-Наура. Подробную информацию по этим вопросам можно получить в книгах [12.4], [12.5]. Я представлю лишь объяснения на примерах, достаточные для того, чтобы разобраться с грамматикой SCL и создавать что-то подобное им самостоятельно.

Грамматика языка в форме Бэкуса-Наура задает структуру текстов, которые можно создавать с помощью этого языка. Строгое определение этой структуры позволяет формальную обработку таких текстов - обнаружение синтаксических ошибок, валидацию более сложных ограничений, генерацию программного кода и т.д.

Структура текстов определяется иерархически, в виде правил. В случае с SCL любой текст (визуальная модель) должен состоять из имени модели, списка сигналов и набора компонент:

<model> :: = <model name><signal_list>+ <component>+

Конструкция <model> называется головной - с нее грамматика начинается. Список сигналов обозначается как <signal_list>. Таких списков, равно как и компонент (<component>), в модели может быть сколько угодно, но обязательно должен быть хоть один, что изображается значком + рядом с тем элементом грамматики, которого "может быть один или много". Список сигналов устроен следующим образом. Он состоит из строк, обозначающих сигналы, которые могут быть посланы и получены экземплярами компонент:

<signal_list> :: = <signal>+
<signal> :: = <signal name>

Конструкции, подобные <signal name> и <model name> обычно называются идентификаторами. Они являются именами (переменных, процедур, сигналов и пр.), задаваемыми пользователями языка при разработке модели. В случае языка SCL идентификаторы являются терминалами, так как не подвергаются дальнейшему разбору в ее грамматике. А нетерминалами называются конструкции, которые являются составными и поддаются дальнейшему разбору. Примерами нетерминалов являются <model>, <signal_list>, <signal>, <component>. В SCL-грамматике идентификаторы обозначаются как обычные нетерминалы, но с добавлением подчеркивания имени.

В языках программирования идентификаторы подвергаются дальнейшей детализации, то есть не являются терминалами. Определяется, из каких символов они могут состоять: не все ASCI-символы могут входить в идентификаторы, например, спецсимволы - $, #, @ и пр. Однако здесь я не стал усложнять простой пример. Для тех, кто хочет более основательно разобраться в теории формальных языков и грамматик, познакомиться с грамматиками реальных языков программирования, узнать, как создаются синтаксические анализаторы программ, можно порекомендовать книги [12.4], [12.5].

Разобранный выше фрагмент грамматики языка SCL можно представить деревом, как показано на рис. 12.2.

Фрагмент грамматики языка SCL в виде дерева

Рис. 12.2. Фрагмент грамматики языка SCL в виде дерева

Продолжим изучать грамматику языка SCL. Конструкция <component> определяется следующим образом:

<component> :: = <component name> <parameters> 
   <method>* [<statechart>] <attribute>*

Видно, что компонента состоит из имени ( <component name> ), параметров ( <parameters> ), набора методов ( <method> ) и атрибутов ( <attribute> ), а также конечного автомата ( <statechart> ). Сразу за нетерминалами <method> и <attribute> следует значок '* ', который указывает на то, что как методов, так и атрибутов в компоненте может быть произвольное количество, в том числе и не быть вовсе. Последняя оговорка отличает символ '* ' от '+ '. Нетерминал <statechart> взят в квадратные скобки. Это означает, что его может не быть, т. е. конечный автомат может у компоненты отсутствовать.

У компоненты есть два параметра, следующих в круглых скобках за ее именем. Первый параметр указывает на то, сколько экземпляров компонент создается при запуске системы, второй - сколько экземпляров одновременно может существовать в системе:

<parameters>::= (<init>, <num>)

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

Конечный автомат включает в себя ссылку на компоненту, к которой он относится ( <component_ref> ), а также набор состояний ( <state>+ ):

<statechart> ::=  <component_ref> <state>+

Прокомментируем элемент <component_ref>. Эта конструкция похожа на идентификатор, т. е. тоже является строковым значением и терминалом, но смысл у нее иной. Она ссылается на другую, существующую в модели, конструкцию. Будем называть такие конструкции ссылками. Они, так же как и идентификаторы, являются терминалами в SCL-грамматике. Ссылки будут обозначаться именами, оканчивающимися на ref.

Состояние устроено так:

<state> ::=  <state name> <transition>*

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

Переход, в свою очередь, устроен следующим образом:

<transition> :: = [<input>]/<action> {; <action>}* <target_state_ref>

Он инициируется определенным сигналом, который принимается и обрабатывается компонентой в этом состоянии (конструкция <input> ), содержит в себе ряд действий ( <action> ) и завершается новым состоянием, в которое экземпляр компоненты переходит, обработав данный входной сигнал (конструкция <target_state_ref> ). В конструкции <transition> содержатся два терминала нового типа, которые еще не рассматривались в этой лекции. Это значок '/ ', который отделяет входной сигнал от действий по его обработке, и символ '; ', разделяющий действия в переходе в том случае, если их более одного. Эти терминалы относятся к тому же типу, что и круглые скобки. Отметим, что фигурные скобки, так же как и квадратные, являются частью грамматики. Они группируют аргумент для операции, обозначаемой символом '*': следующее действие в переходе должно быть отделено символом ';' от предыдущего, в то время как последнее действие не должно иметь после себя этот разделитель.

Действие в переходе может быть либо посылкой сигнала другой компоненте, либо вызовом метода данного объекта:

<action> :: = <method_invocation>| <send>

Значок '|' SCL-грамматики обозначает альтернативу.

Ниже представлена вся SCL-грамматика целиком, с некоторыми добавлениями, которые мне кажутся очевидными.

<model> :: = <model name><signal list>+ <component>+
<component> :: =  <component name> <parameters> <method>* [<statechart>] <attribute>*
<parameters>::= (<init>, <num>)
<statechart > ::=  <component_ref><state>+
<state> ::=  <state name> <transition>* 
<transition> :: = [<input>]/<action> (; <action>)* <target_state>
<action> :: = <method_invocation>| <send>
<method> :: = < method name>()
<attribute> ::= <attribute name> <attribute_type>
<attribute_type> :: = <attribute type name>
<target_state> :: = <state_ref>
<send>::= <signal_ref>
<input>::= <signal_ref>
<method_invocation > :: = <method_ref>()
< Лекция 11 || Лекция 12: 1234 || Лекция 13 >
Анна Митюрёва
Анна Митюрёва

http://www.intuit.ru/studies/courses/1041/218/info

С мобильного приложения доступ есть, а через сайт не отображается. Печально =(

Сергей Москалёв
Сергей Москалёв
Россия, Москва, Московский Инженерно Физический Институт, 1977