Generator User Guide Demo5 #
Generator User Guide Demo 5 #
In this demo we will learn how to use generation scripts and utility classes.
There are two kinds of generation scripts: pre-processing and post-processing scripts.
Pre-processing scripts are invoked before applying the generator rules and they usually alter the input model in a way that makes it easier for further processing by the rules.
Post-processing scripts are invoked after all generator rules have finished and they are applied to the output model.
Additionally, in case of having multiple scripts in a generator you can influence the order, in which the scripts will run.
New Language #
We'll start with an exact copy of the demoLang4 language.
create new language 'generator_demo.demoLang5'
in the language properties dialog add extended languages: 'jetbrains.mps.sampleXML' and 'jetbrains.mps.baseLanguage'
create a new generator for this language if it has not been created (see Demo 1 for details)
delete the (empty) mapping configuration 'main' from demoLang5 generator
copy-paste all nodes from the demoLang4 generator to the demoLang5 generator
New Test Model #
in the 'test_models' solution clone the model 'test4' into 'test5'
in the model properties dialog replace 'engaged on generation' language demoLang4 -> demoLang5 (see Demo 2 for details)
in the model 'test5' open the 'Panel' document
add a Text node to the 'panel' element:

Pre-processing Script #
Our demoLang5 generator doesn't support text nodes, but text node in this context has the same meaning as a 'label' element with a 'text' attribute set. Therefore, instead of adding more rules to our generator, we will add a pre-processing script, which will convert all text nodes in the input model into 'label' elements and let existing rules do the rest of the job.
in the 'main@generator' model if the demoLang5 generator create a root node of type mapping script
give it a name 'fix_text'
set script kind = pre-process input model
set modifies model = true, since we're going to alter the input model inside the script
enter the code, which will perform a search and a replace of all text nodes in the input model:

add the 'fix_text' script to mapping configuration 'main' to the pre-processing scripts section:

First Test #
Re-build the language and check out the generated text from the 'test5' model:

You can see that a label was correctly created for the 'Hello everybody' text and that the label is being added into the panel.
Utility Classes in Generator #
Now, let's suppose we got an idea to fix possible syntax and stylistic errors in the generated texts. We'll create a post-processing script to do that. These NLP algorithms tend to be quite complex, so let's develop them in a separate utility class, instead of embedding them into the script directly.
The issue here is that a utility class cannot be created in the generator model 'main@generator' directly, because then it would be treated as a root template, just like any other root node in any 'generator'-stereotyped model would.
We'll have to create another model in the generator module:
select the generator node (the demoLang5 generator) in the tree and choose New->Model in the popup menu:

give the new model name: 'util':

Make sure you clear our the Stereotype text field
in model 'util' create class 'TextUtil'
add static method 'fixText()' to class 'TextUtil':

We are going to call the 'fixText()' method in a post-processing script and pass the output model as a parameter. The output model contains classes, methods, expressions and so on. Thus we are manipulating a java-like syntax tree here.
The 'fixText()' method will replace all strings starting with "MPS" with strings that start with "JetBrains MPS".
Post-processing Script #
Now we can use this utility method 'fixText()' in a post-processing script:
in model 'main@generator' (in the demoLang5 generator) create a new mapping script
give it a name 'refine_text'
-
import the 'generator_demo.demoLang5.generator.util' model to model 'main@generator' (see Demo 1 for details on model importing)
in the 'refine_text' mapping script enter the code as shown:

add the 'refine_text' script to the post-processing scripts section in the mapping configuration 'main':

Re-build the generator.
You can use Ctrl/Cmd-F9 (generate all changed models in module). Note that Shift-F9 (generate current model) is not enough any more because now we have two models requiring generation.
Second Test #
Generate model 'test5' and preview the generated text:

Notice the label now holds a "JetBrains MPS" text.