Simple "optional suffix"

Let's suppose I'm trying to create in MPS the following language:

concept MyVar extends BaseConcept implements INamedConcept

  TypeString typeString 0..1

And I want the following editor behavior to happen:

I can type this:


and the editor will just show that, and parse it as a MyVar with no typeString field.

I can also type this:


and the editor will parse it as a MyVar with a typeString field. (The TypeString concept here just has a simple editor, that edits a name.)

So in other words I wanna let the user be able to specify an optional suffix, like ActionScript for example, where you can explicitly specify the type or you can choose to omit it.

How should I do this in MPS? If I just declare the editor to be a horizontal collection of {name}, ":", and %typeString%, then if I type abcde:sometype, it will only interpret it as the whole name, and will just ignore the ":" in between.

To make it working I suggest:
1. Creating following editor for MyVar concept:
[- { name } ?[- : ^{ type } -] -]
where "?" before a collection means corresponding collection will be created conditionally based on following query specified in an inspector of this collection:
show if 

(scope, editorContext, node)->boolean { 
  node.type != null; 
as a result you will have editor displaying only name property of MyVar concept if no type was specified.

2. Then you should add following constraint for property:
property {name} 
  is valid:(node, propertyValue, scope)->boolean { 
    propertyValue.indexOf(" ") == -1 && propertyValue.indexOf(":") == -1; 
by doing this you prevent MPS from treating ":" or " " chars as a part of MyVar name

3. Add Right-Transform action adding empty name to existing MyVar instance if you press ":". To do it you have to create new "actions" aspect in your language (if it was not created before), open it an create new "Transform Menu Actions" root there with following content:
side transform actions AddType           
right transformed node: MyVar tag: default_  //<no description> 
  condition :             
  common initializer :    
    <no common variables> 
    <no common initializer>              
  actions :
    add custom items  (output concept: MyVar)    
      simple item         
        matching text     
        description text  
          Add Type        
        do transform      
          (operationContext, scope, model, sourceNode, pattern)->node<> { 
  sourceNode.type = ""; 

As a result you should be able to type: "myVariableName" to edit the name of MyVar concept and if you press ":" or " :" in the end of MyVar name then additional (empty) type property should be added to the model, so editor will be transformed to:
myVariableName : <no type>
Thanks so much Alex! Sorry that I already figured out the solution. However, I think this is a great guide for those who are looking for something similar!

I think MPS deserves some better documentation. I'm sure JetBrains is planning on that, perhaps when the software is more stable in its design. I'm waiting to see that happening!

Please sign in to leave a comment.