Прошел год как первый прототип интеграции Virtual World Framework & Ometa был представлен на международной конференции SPLASH'14 на семинаре по будщему программирования Future Programming Workshop. В 2015 году вышла в свет новая версия объектно-ориентированного языка для создания языков Ometa под именем Ohm. Как и OMeta, новый язык так же поддерживает объектно-ориентированное создание грамматик, распознавание строк и структурных типов данных, но теперь грамматики полностью отделены от семантических действий над ними.
В этом сообщении я хотел бы представить вашему вниманию обновленный прототип, который базируется на новом языке Ohm!
Чтобы попробовать прототип в действии, просто откройте эту ссылку в браузере и войдите в виртуальный мир, содержащий генератор L-систем. Вы можете модифицировать этот мир, скопировав его или создав новый. В библиотеке "Content Library" располагающейся слева в инструментарии миров, находятся примеры L-систем от треугольника Серпинского до снежинки Коха.
Вы можете модифицировать параметры выбранного объекта L-системы в реальном времени: угол, количество итераций, аксиомы и правила. Более того в редакторе скриптов "Script Editor" вы можете изменить грамматику выбранного объекта, не нарушая работу других объектов мира.
Первые шаги по работе с прототипом
Ниже приведены шаги, выполнив которые вы сможете попробовать самостоятельно как прикрепить грамматику к объекту в виртуальном пространстве и добавить соответствующие семантические действия, используя версию прототип Крестьянство SDK, объединяющий инструментарий виртуальных миров ADL Sandbox и язык Ohm. В качестве примера мы возьмем грамматику для арифметического калькулятора, которая доступна из обучающих материалов по языку Ohm.
Итак, сначала мы определим грамматику для распознавания простых арифметических выражений типа "(5+7)*4"; далее мы добавим семантические действия, которые позволят вычислять распознанные выражения на языке JavaScript; далее мы прикрепим созданную грамматику к объекту виртуального мира, так чтобы результат вычислений отображался на самом же объекте.
Работающий виртуальный мир с грамматикой арифметического калькулятора доступен здесь: http://live.net.ru/adl/sandbox/world/WRpbHEuHfYGmUm54
Для начала работы, зарегистрируйтесь пожалуйста на сайте виртуальных миров: http://live.net.ru проекта http://www.krestianstvo.org.
Будучи зарегистрированными, вы сможете создавать свои миры или клонировать существующие для изменения и экспериментов.
1. Создайте новый мир и войдите в него:
2. Внутри мира создайте объект "3D Text" для последующего присоединения грамматики к нему и визуализации результата:
3. Откройте редактор скриптов "Script Editor" для выбранного объекта (3D text) и создайте новый параметр с именем: ohmCalc. Скопируйте содержимое исходного кода грамматики в редактор. Важно чтобы имя начиналось с префикса 'ohm'! Это укажет среде виртуальных миров, что для параметра должны будут создаться автоматически другие необходимые параметры и методы (язык Omh доступен после загрузки мира по глобальной переменной _ohm). После создания параметра, объект грамматики автоматически сгенерируется и будет сохранен под именем Calc.
Исходный код грамматики для арифметического калькулятора:
Arithmetic {
Exp
= AddExp
AddExp
= AddExp "+" MulExp -- plus
| AddExp "-" MulExp -- minus
| MulExp
MulExp
= MulExp "*" ExpExp -- times
| MulExp "/" ExpExp -- divide
| ExpExp
ExpExp
= PriExp "^" ExpExp -- power
| PriExp
PriExp
= "(" Exp ")" -- paren
| "+" PriExp -- pos
| "-" PriExp -- neg
| ident
| number
ident (an identifier)
= letter alnum*
number (a number)
= digit* "." digit+ -- fract
| digit+ -- whole
}
4. Создайте метод для выбранного объекта (3D text), в котором мы определим семантические действия для грамматики. Объект семантики доступен по автоматически сгенерированнму параметру Engine.getProperty(this.id, 'semanticsCalc'). Скопируйте ниже приведенный код операции 'interpret' в новый метод с именем addOperationCalc
Исходный код: addOperationCalc
function addOperationCalc()
{
var constants = {pi: Math.PI, e: Math.E};
var s = _LangManager.ohmLangs[this.id]["Calc"]["semantics"];
s.addOperation('interpret', {
Exp: function(e) {
return e.interpret();
},
AddExp: function(e) {
return e.interpret();
},
AddExp_plus: function(x, _, y) {
return x.interpret() + y.interpret();
},
AddExp_minus: function(x, _, y) {
return x.interpret() - y.interpret();
},
MulExp: function(e) { return e.interpret(); },
MulExp_times: function(x, _, y) { return x.interpret() * y.interpret(); },
MulExp_divide: function(x, _, y) { return x.interpret() / y.interpret(); },
ExpExp: function(e) { return e.interpret(); },
ExpExp_power: function(x, _, y) { return Math.pow(x.interpret(), y.interpret()); },
PriExp: function(e) { return e.interpret(); },
PriExp_paren: function(_, e, _) { return e.interpret(); },
PriExp_pos: function(_, e) { return e.interpret(); },
PriExp_neg: function(_, e) { return -e.interpret(); },
ident: function(_, _) {
return constants[this.interval.contents] || 0;
},
number: function(_) {
return parseFloat(this.interval.contents);
}
});
}
5. Далее нам нужно добавить вызов функции addOperationCalc() из метода initGrammarCalc() и вызвать его для инициализации семантических действий. После добавления кода, нажмите кнопку Call Method.
function initGrammarCalc()
{
//console.log('Init grammar: Calc');
this.addOperationCalc();
}
6. Теперь, мы готовы протестировать грамматику. Создайте новый метод с именем "test" и скопируйте код для него. Нажмите кнопку Call Method.
function test()
{
var str = '(5+7)*4';
var gram = _LangManager.ohmLangs[this.id]["Calc"]["grammar"];
var sem = _LangManager.ohmLangs[this.id]["Calc"]["semantics"];
var r = gram.match(str);
var n = sem(r);
this.text = n.interpret();
}
Если все в порядке, то вы должны увидеть результат распознавания и вычисления арифметического действия из строки "(5+7)*4"
Если что-то не работает, посмотрите виртуальный мир с подключенной грамматикой арифметического калькулятора здесь