0

My grammar is given by:

Model:
    'module' (mn=ID)?
        (func+=Function)+
    'end_module'
;

Function:
    'function' name=ID '('')'
        (vars+=ID)*
    'end_function'
;

I can find the token like 'function', '(' etc.

  • How can If force a new line after the token 'module' if the optional data mn does not exist and after mn if it does exist?
  • How can I indent the block begin 'module' and 'end_module' as well as 'function' and 'end_function'?

The formatting I am looking for:

module test
  function fdf ()
    str1
    str2
  end_function

  function ff ()
  end_function
end_module

So far I do generate the formatting stubs by using: formatter = { generateStub = true }

Johan
  • 575
  • 5
  • 21

2 Answers2

3

that should be rather straight forward e.g.

@Inject extension MyDslGrammarAccess

def dispatch void format(Model model, extension IFormattableDocument document) {
    model.regionFor.keyword(modelAccess.end_moduleKeyword_3).prepend[newLine] 
    if (model.mn != null) {
        model.regionFor.feature(MyDslPackage.Literals.MODEL__MN).append[newLine]
        interior(
            model.regionFor.feature(MyDslPackage.Literals.MODEL__MN), 
            model.regionFor.keyword(modelAccess.end_moduleKeyword_3)
        ) [indent]
    } else {
        model.regionFor.keyword(modelAccess.moduleKeyword_0).append[newLine]
        interior(
            model.regionFor.keyword(modelAccess.moduleKeyword_0),
            model.regionFor.keyword(modelAccess.end_moduleKeyword_3)
        ) [indent]
    }
    for (Function func : model.getFunc()) {
        func.format;
    }
}

def dispatch void format(Function function, extension IFormattableDocument document) {
    function.regionFor.keyword(functionAccess.functionKeyword_0).append[newLine].prepend[newLine]
    function.regionFor.keyword(functionAccess.end_functionKeyword_5).prepend[newLine]
    interior(
        function.regionFor.keyword(functionAccess.functionKeyword_0),
        function.regionFor.keyword(functionAccess.end_functionKeyword_5)
    ) [indent]
}
Christian Dietrich
  • 11,778
  • 4
  • 24
  • 32
2

As proposed in Max's Answer, it is possible to cope with whitespace-aware languages starting from Xtext v2.8. Check it out!.

In your case, I guess you should define your grammar as follows:

Model:
    'module' (mn=ID)?
    BEGIN
        (func+=Function)+
    END
    'end_module'
;

Function:
    'function' name=ID '('')'
    BEGIN
        (vars+=ID)*
    END
    'end_function'
;

terminal BEGIN: 'synthetic:BEGIN';
terminal END: 'synthetic:END';

In case you would also want to allow 'empty-bodied' functions, I guess you should change the rule above as follows:

Function:
    'function' name=ID '('')'
    (BEGIN
         (vars+=ID)*
    END)?
    'end_function'
;

Hope it helps!

Community
  • 1
  • 1
Lorenzo Addazi
  • 325
  • 3
  • 12
  • Yes it helps a lot. I have to format the code by hand. how must the body of `format(Model, extension IFormattableDocument)` look to do automatic formatting? – Johan Oct 08 '16 at 13:20
  • 1
    You can take a look at the 'Home Automation language' example project from Xtext, together with the documentation about Whitespace-Aware Languages (linked in the answer above). I suggest you to start from the workflow file (.mwe2) to understand how to generate a custom formatter stub. Then, 'org.eclipse.xtext.example.homeautomation.formatting2.RuleEngineFormatter' and 'org.eclipse.xtext.example.homeautomation.parser.antlr' will contain the actual implementation you need to adapt for your language. – Lorenzo Addazi Oct 08 '16 at 14:28
  • In the example `RuleEn‌​gineFormatter` uses `org.eclipse.xtext.example.homeautomation.ruleEngine.Declaration` but my project does not created similar files. All the related `org.eclipse.xtext.example.homeautomation.ruleEngine.*` are missing in my project. – Johan Oct 08 '16 at 15:04
  • 1
    In order to generate the formatter for your dsl, you need to insert formatter = {generateStub = true} in the 'language' component inside the workflow file (.mwe2) and run the workflow. Note that 'ruleEngine' is the language name for the example and 'Declaration' corresponds to one of its rules. In your project, you will have a 'Formatter' using the classes corresponding to the rules of your language. – Lorenzo Addazi Oct 08 '16 at 15:12
  • @Addazi, thanks for the help. You answered 50% of my question and Dietrich the other 50%. The site allow me to selection only one correct answer. – Johan Oct 09 '16 at 18:03