XText была выпущена как часть выпуска поезда Затмение Галилео 24 июня 2009 года XText является основой для построения DLSS ( d omain сек pecific л anguages). Фактически это можно рассматривать как DSL для определения DSL.
В этой статье мы разработаем небольшой DSL для определения сущностей.
Загрузить и установить
Перейдите на http://xtext.itemis.com и загрузите дистрибутив Xtext, соответствующий вашей платформе. У нас есть все основные платформы: Windows, Mac OSX Carbon, Mac OSX Cocoa 64, Mac OSX Cocoa 32, Linux Gtk 64, Linux Gtk 32.
Для установки распакуйте файл дистрибутива в каталог по своему вкусу.
Пользователи Windows, пожалуйста, убедитесь, что вы распаковали каталог, расположенный рядом с корнем вашей файловой системы! Eclipse содержит файлы и папки с длинными именами, которые могут быть трудно обрабатывать для Windows.
Создать новый проект
После запуска Eclipse и создания нового рабочего пространства (или использования существующего) создайте новый проект Xtext, выбрав « Файл» -> «Новый … Проект … -> Проект Xtext» . В этой статье мы создаем DSL для описания сущностей, поэтому давайте перейдем к следующим настройкам:
- Название основного проекта: org.xtext.example.entity
- Имя языка: org.xtext.example.Entity
- Расширение DSL-файла: сущность
- Создать генератор проекта: да
Нажмите Finish, чтобы Xtext создал три проекта, составляющих ваш DSL:
- org.xtext.example.entity — этот проект содержит сам DSL, включая всю внутреннюю инфраструктуру, такую как анализатор и метамодель.
- org.xtext.example.entity.ui — как следует из названия, этот проект содержит весь код DSL, ориентированный на пользовательский интерфейс: редактор, схема, помощник по содержимому и т. д.
- org.xtext.example.entity.generator — этот проект содержит генератор кода, который преобразует сценарии DSL (или модели), которые вы пишете в DSL, во что-то полезное. В нашем примере мы создадим несколько POJO и DAO из наших моделей.
По завершении создания этих трех проектов Xtext открывает файл Entity.xtext , который содержит образец грамматики, который мы изменим через секунду.
Определите грамматику для вашего DSL
Далее нам нужно определить грамматику для нашего DSL. Чтобы упростить нам задачу, давайте сначала запишем образец модели. Откройте org.xtext.example.entity.generator / src / model / MyModel.entity и введите следующий текст:
typedef String
typedef Integer
typedef Date mapsto java.util.Date
entity Person {
String name
String surName
Date birthDay
Address home
Address work
}
entity Boss extends Person {
Person* employees
}
entity Address {
String street
String number
String city
String ZIP
}
Большая часть этой модели должна быть довольно очевидной, но есть две вещи, на которые стоит обратить внимание:
- Мы определяем наш собственный список типов данных, чтобы получить определенную степень гибкости, т. Е. Сопоставлять их с различными типами на главном языке, как это видно для типа данных Date , который отображается на java.util.Date (мы могли бы также решили сопоставить его с java.sql.Date
- Звезда (*) обозначает кратность. Мы также могли бы выбрать квадратные скобки ( Person [] employee ) или что-то совершенно другое — это во многом вопрос вкуса.
Давайте выведем грамматику для этой модели. Откройте org.xtext.example.entity / src / org / xtext / example / Entity.xtext , удалите все его содержимое и введите следующее:
grammar org.xtext.example.Entity with org.eclipse.xtext.common.Terminals
generate entity "http://www.xtext.org/example/Entity"
Первая строка указывает, что мы хотим, чтобы новая грамматика была получена из (встроенных) грамматических терминалов , которые определяют некоторые основные терминальные правила (такие как STRING, ID и т. Д.). Если вам интересно, нажмите CTRL + клик по названию языка, чтобы перейти к его определению.
Вторая строка определяет имя и URI пространства имен для нашей собственной грамматики.
Давайте теперь определим, что наш DSL поддерживает типы. Добавьте следующие строки:
Model:
(types+=Type)*;
Type:
TypeDef | Entity;
Это говорит Xtext, что наша Модель содержит любое число (то есть 0..N , как объявлено * ) типа s. Что именно Тип должен быть указан. Очевидно, типом может быть либо TypeDef, либо Entity :
TypeDef:
"typedef" name=ID ("mapsto" mappedType=JAVAID)?;
TYPEDEF начинается с ключевым словом ЬурейиМ , с последующим ID составляя свое название. После имени мы можем по желанию (отсюда и знак вопроса в конце) добавить предложение mapsto . Фрагмент mappedType = JAVAID указывает, что TypeDef позже будет иметь атрибут с именем mappedType типа JAVAID. Поскольку JAVAID еще не определен, нам нужно сделать это:
JAVAID:
name=ID("." ID)*;
Таким образом, JAVAID — это последовательность идентификаторов и точек, составляющая полное имя типа Java, например, java.util.Date .
Далее давайте определим, как моделировать объекты:
Entity:
"entity" name=ID ("extends" superEntity=[Entity])?
"{"
(attributes+=Attribute)*
"}";
Как вы уже догадались, сущность начинается с ключевого слова сущности , за которым следует идентификатор в качестве имени. Они могут дополнительно расширять другую сущность. Окружение вызова правила квадратными скобками означает «это перекрестная ссылка», то есть ссылка на уже существующий элемент.
У сущности s есть атрибуты s (если быть точным, любое число), поэтому мы должны определить, как выглядят атрибуты :
Attribute:
type=[Type] (many?="*")? name=ID;
Теперь вы должны быть в состоянии прочитать это правило: Атрибут имеет тип, который является перекрестной ссылкой на Тип (который является либо TypeDef, либо Entity ), он имеет дополнительный индикатор множественности (звездочка) и — конечно — если есть имя.
Ваша грамматика должна выглядеть так:
grammar org.xtext.example.Entity with org.eclipse.xtext.common.Terminals
generate entity "http://www.xtext.org/example/Entity"
Model:
(types+=Type)*;
Type:
TypeDef | Entity;
TypeDef:
"typedef" name=ID ("mapsto" mappedType=JAVAID)?;
JAVAID:
name=ID("." ID)*;
Entity:
"entity" name=ID ("extends" superEntity=[Entity])?
"{"
(attributes+=Attribute)*
"}";
Attribute:
type=[Type] (many?="*")? name=ID;
Компиляция DSL
Теперь пришло время увидеть плоды нашего труда. Но сначала нам нужно скомпилировать нашу грамматику. Xtext создаст:
- парсер
- сериализатор
- метамодель Ecore
- полноценный редактор Eclipse
из этой грамматики. Чтобы это произошло, выберите org.xtext.example.entity / src / org / xtext / example / GenerateEntity.mwe и выберите Run As -> MWE Workflow из контекстного меню. Xtext теперь создаст всю инфраструктуру для вашего DSL, и через несколько секунд у вас должен появиться новый DSL, включая отличный редактор.
Принимая это за спин
Видеть значит верить, так что давайте возьмем редактор DSL для тест-драйва. Выберите проект DSL org.xtext.example.entity и в контекстном меню выберите « Запуск от имени» -> «Приложение Eclipse» . Второй экземпляр Eclipse будет запущен.
В этом новом экземпляре создайте новый пустой проект ( Файл -> Новый -> Проект … -> Общие -> Проект . Создайте новый файл Sample.entity в новом проекте.
Теперь вы можете вставить модель, которую мы разработали выше, или ввести новую модель:
Использование модели
Теперь, когда у нас есть модный редактор для нашего DSL, мы хотим превратить модели, которые мы можем создать с помощью этого редактора, во что-то значимое. Это, однако, будет темой следующего выпуска.
Больше информации
Не стесняйтесь обсуждать эту статью в разделе комментариев моего блога . Если у вас есть какие-либо технические вопросы относительно Xtext, у нас есть отличная группа новостей, где коммиттеры отвечают на ваши вопросы. Мы также предлагаем профессиональную (коммерческую) поддержку , то есть индивидуальные тренинги для ускорения работы вашей команды. Просто напишите нам , мы будем рады обсудить детали с вами.