Я пытаюсь создать грамматику для системы управления освещением и добился значительных успехов при тестировании с помощью инструмента tree gui, но, похоже, все разваливается, когда я пытаюсь внедрить его в свое приложение.
Базовая структура языка: [Источник] [Маска] [Команда] [Назначение] . Маска является необязательной, поэтому супер простой пример ввода может выглядеть следующим образом: Fixture 1 @ 50 , который обходит маску. Приспособление 1 является источником, @ является командой, а 50 является местом назначения, которое в этом случае является значением интенсивности.
У меня нет проблем с этим типом ввода, но все усложняется, когда я пытаюсь создать более сложный выбор источника. Допустим, я хочу выбрать диапазон приборов и удалить несколько из выбора, а затем добавить больше приборов после.
Светильник с 1 по 50 - 25 - 30 - 35 + 40> 45 @ 50
Это очень распространенный синтаксис в существующих системах управления, но я поставлен в тупик, как разработать грамматику для этого таким образом, чтобы сделать интеграцию в мое приложение не слишком болезненной.
Пользователь может так же легко набрать следующее:
1 Через 50 - 25 - 30 - 35 + 40> 45 @ 50
Поскольку sourceType (fixture) не предоставлен, его вывод.
Чтобы попытаться справиться с вышеуказанными ситуациями, я написал следующее:
grammar LiteMic;
/*
* Parser Rules
*/
start : expression;
expression : source command destination
| source mask command destination
| command destination
| source command;
destination : sourceType number
| sourceType number sourceType number
| number;
command : COMMAND;
mask : SOURCETYPE;
operator : ADD #Add
| SUB #Subtract
;
plus : ADD;
minus : SUB;
source : singleSource (plus source)*
| rangeSource (plus source)*
;
singleSource : sourceType number #SourceWithType
| number #InferedSource
;
rangeSource : sourceRange (removeSource)*
;
sourceRange : singleSource '>' singleSource;
removeSource : '-' source;
sourceType : SOURCETYPE;
number : NUMBER;
compileUnit
: EOF
;
/*
* Lexer Rules
*/
SOURCETYPE : 'Cue'
| 'Playback'
| 'List'
| 'Intensity'
| 'Position'
| 'Colour'
| 'Beam'
| 'Effect'
| 'Group'
| 'Fixture'
;
COMMAND : '@'
| 'Record'
| 'Update'
| 'Copy'
| 'Move'
| 'Delete'
| 'Highlight'
| 'Full'
;
ADD : '+' ;
SUB : '-' ;
THRU : '>' ;
/* A number: can be an integer value, or a decimal value */
NUMBER : [0-9]+ ;
/* We're going to ignore all white space characters */
WS : [ \t\r\n]+ -> skip
;
Запуск команды для grun gui приводит к следующему:
У меня был некоторый успех, когда я смог переопределить Listener для AddRangeSource, поскольку я могу циклически проходить и добавлять правильные типы, но все это разваливается, когда я пытаюсь удалить диапазон.
1> 50 - 30> 35 @ 50
Это создает проблему, поскольку удаление диапазона соответствует «addRangeSource».
Я почти уверен, что упускаю что-то очевидное, и я пробираюсь через книгу, которую я купил на Амазоне, но мне все еще не ясно, как архивировать то, что я ищу, и я смотрю на это уже неделю.
Для большей ясности ниже приведено дерево для более сложного запроса, который кажется нормальным, если не считать выбора.
У кого-нибудь есть какие-нибудь указатели / предложения о том, где я ошибаюсь?
Ура,
Майк