DSL с XText для PlantUML
В настоящее время я пытаюсь создать DSL для диаграмм классов PlantUML. Я новичок в Xtext и не могу разобраться в нескольких вещах. Прежде чем я перечислю свои проблемы, я покажу вам некоторые части моей текущей грамматики:
ClassUml:
{ClassUml}
'@startuml' umlElements+=(ClassElement)* '@enduml';
ClassElement:
Class
| Association;
Class:
{Class}
'class' name=ClassName
(color=ColorTag)?
('{' (classContents+=ClassContent)* '}')?;
ClassContent:
Attribute | Method;
ClassName:
(ID | STRING);
Attribute:
{Attribute}
(visibility=Visibility)? name=ID (":" type=ID)?;
Method:
{Method}
(visibility=Visibility)? name=METHID
(":" type=ID)?;
Association:
{Association}
(classFrom=[Class]
associationType=Bidirectional
classTo=[Class])
|
(classTo=[Class]
associationType=UnidirectionalLeft
classFrom=[Class])
|
(classFrom=[Class]
associationType=UnidirectionalRight
classTo=[Class])
(':' text+=(ID)*)?;
Bidirectional:
{Bidrectional}
('-' ("[" color=ColorTag "]")? '-'?)
| ('.' ("[" color=ColorTag "]")? '.'?);
UnidirectionalLeft:
{UnidirectionalLeft}
('<-' ("[" color=ColorTag "]")? '-'?)
| ('<.' ("[" color=ColorTag "]")? '.'?);
UnidirectionalRight:
{UnidirectionalRight}
((('-[' color=ColorTag "]")|'-')? '->')
| ((('.[' color=ColorTag "]")|'.')? '.>');
ColorTag:
(COLOR | HEXCODE);
enum Visibility:
PROTECTED='#'
| PRIVATE='-'
| DEFAULT='~'
| PUBLIC='+';
terminal COLOR:
"#"
('red') | ('orange');
terminal HEXCODE:
"#"
('A' .. 'F'|'0' .. '9')('A' .. 'F'|'0' .. '9')('A' .. 'F'|'0' .. '9')
('A' .. 'F'|'0' .. '9')('A' .. 'F'|'0' .. '9')('A' .. 'F'|'0' .. '9');
terminal STRING:
'"' ('\\' . | !('\\' | '"'))* '"';
terminal ID:
('a'..'z' | 'A'..'Z' | '_' | '0'..'9' | '\"\"' | '//' | '\\')
('a'..'z' | 'A'..'Z' | '_' | '0'..'9' | '\"\"' | '//' | '\\' | ':')*;
Я пропустил другие типы ассоциаций (-*, --o, - |>), потому что я определил их таким же образом.
Проблемы
1. Перечисление видимости '#' не работает без отделения от имени метода / атрибута. Но все остальные случаи (+,-,~) в порядке, с пробелом и без него.
2. В большинстве случаев ассоциации не работают. Я перечислил несколько примеров:
' Working '
Alice -* Bob : Hello
Alice - Bob
Alice .o Bob
Alice <|-[#002211]- Bob
Alice *-[#red]- Bob
Alice -[#000000]-> Bob
Alice .[#red].> Bob
' Not Working '
Alice *-- Bob
Alice --* Bob
Alice .. Bob
Alice -[#ff0022]- Bob
Alice <-- Bob
Alice ..> Bob
Alice -- Bob
- Я не знаю, как я могу использовать перекрестные ссылки для классов, которые были определены STRING, а не ID.
Также я предполагаю, что дополнительный терминал для имени метода является странным решением и должен обрабатываться по-другому.
1 ответ
1) Цвет должен быть правилом парсера, а не терминальным правилом. Также удалите правило Hex и просто используйте измененное правило ID.
Color:
"#" ('red' | 'orange' | ID);
2) Убедитесь, что вы унифицировали различия, например, существует конфликт между
Bidirectional:
...
('-' ("[" ...;
а также
UnidirectionalRight:
((('-[' ...;
последовательность '-[' всегда будет соответствовать последней версии. Вы должны создать одно правило AssociationType и заставить его работать для всех случаев. Что-то вроде этого:
Association:
{Association}
(classFrom=[Class | ClassName]
associationType=AssociationType
classTo=[Class | ClassName])
(':' text+=(ID)*)?;
AssociationType:
{AssociationType}
left?='<'? ('-'|'.') ("[" color=Color "]")? ('-'|'.') right?='>'?;
3) Вы также можете разрешить STRING в перекрестных ссылках, используя следующий синтаксис для перекрестных ссылок: classFrom=[Class|ClassName]