How to structure my XText terminals? WORDS/SL_STRING/ML_STRING

1.2k views Asked by At

In my XText DSL, I want to be able to use three different kinds of text terminals. They are all used for adding comments on top of arrows drawn in a UML diagram:

terminal WORD:

Actor -> Actor: WORD

terminal SL_STRINGS:

Actor -> Actor: A sequence of words on a single line

terminal ML_STRINGS:

    Actor -> Actor: A series of words on 
                      multiple 
                      lines

My initial approach was to use the ID terminal from the org.eclipse.xtext.common.Terminals as my WORD terminal, and then just have SL_STRINGS be (WORD)*, and ML_STRINGS be (NEWLINE? WORD)*, but this creates a lot of problems with ambiguity between the rules.

How would I go about structuring this in a good way?


More information about the project. (And as this is the first time working with XText, please bear with me):

I am trying to implement a DSL to be used together with the Eclipse Plugin for PlantUML http://plantuml.sourceforge.net/sequence.html mainly for Syntax Checking and Colorization. Currently my grammar works as such:

Model:
    (diagrams+=Diagram)*;

Diagram:
    '@startuml' NEWLINE (instructions+=(Instruction))* '@enduml' NEWLINE*
;

An instruction can be lots of things:

Instruction: 
((name1=ID SEQUENCE name2=ID (':' ID)?) 
| Definition (Color)?
| AutoNumber
| Title
| Legend
| Newpage
| AltElse
| GroupingMessages
| Note
| Divider
| Reference
| Delay
| Space
| Hidefootbox
| Lifeline
| ParticipantCreation
| Box)? NEWLINE
;

Example of rules that need different kinds of text terminals:

Group:
'group' TEXT
;

Reference:
    'ref over' ID (',' ID)* ((':' SL_TEXT)|((ML_TEXT) NEWLINE 'end ref'))
;

For Group, the text can only be on one line, while for Reference, the text can be on two lines if there is no ":" follwing the rule call.

Currently my terminals look like this:

terminal NEWLINE    : ('\r'? '\n');

// Multiline comment begins with /', and ends with '/
terminal ML_COMMENT : '/\'' -> '\'/';

// Singleline comment begins with ', and continues until end of line.
terminal SL_COMMENT : '\'' !('\n'|'\r')* ('\r'? '\n')?;

// INT is a sequence of numbers 0-9.
terminal INT returns ecore::EInt: ('0'..'9')+;

terminal WS         : (' '|'\t')+;

terminal ANY_OTHER: .;

And I want on top of this to add to this add three new terminals that takes care of the text.

1

There are 1 answers

3
Franz Becker On BEST ANSWER

You should implement a data type rule in order to achieve the desired behavior. Sebastian wrote an excellent blog post on this topic which can be found here: http://zarnekow.blogspot.de/2012/11/xtext-corner-6-data-types-terminals-why.html

Here is a minimal example of a grammar:

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
    greetings+=Greeting*;

Greeting:
    'Example' ':' comment=Comment;

Comment:
    (ID ('\r'? '\n')?)+ 
;

That will allow you to write something like this:

Example: A series of words

Example: A series of words on
    multiple lines

You then may want to implement your own value converter in order to fine-tune the conversion to a String.

Let me know if that helps!