The Pattern language
The pattern language has a single purpose - to define patterns of model structures. Those patterns form visual representations of nodes you want to match. A pattern matches a node if the node's property values are equal to those specified in the pattern, node's references point to the same targets that the ones of the pattern do and the corresponding children match the appropriate children of the pattern.
Also patterns may contain variables for nodes, references and properties, which then match any node/reference/property. On top of that the variables will hold the actual values upon a successful match.
The single most important concept of the pattern language is PatternExpression. It contains a pattern as its single arbitrary node. Also, the node can specify the following variables:
- #name - a node variable, a placeholder for a node. Stores the matching node
- #name - a reference variable, a placeholder for a reference. Stores the reference's target, i.e. a node.
- $name - a property variable, a placeholder for a property value. Stores the property value, i.e. a string.
- *name - a list variable, a placeholder for nodes in the same role. Stores the list of nodes.
Antiquotations may be in particular useful when used inside a pattern, just like inside quotations (see Antiquotations).
1. The following pattern matches against any InstanceMethodDeclaration without parameters and a return type:
2. The following pattern matches against a ClassifierType with the actual classifier specified inside an antiquotation expression and with any quantity of any type parameters:
class type's parameters
used as wildcard, its contents is ignored. Means that parameters are arbitrary
Patterns are typically used as conditions in match statements. Pattern variables can be referenced from inside of the match statement.
this piece of code examines a node n and checks whether it satisfies the first or the second condition. Then the statement in the corresponding (matching) block is executed. A pattern variable $name is used in a first block to print out the name of a node. In our case the node holds a variable declaration.
Patterns are also used in several other language constructs in MPS. They may appear:
- as conditions on applicable nodes of typesystem/replacement/subtyping/other rules of typesystem language (See Inference rules)
- as supertype patterns in coerce statement and coerce expression (See Coerce)
- as conditions on node in generator rules
- as pattern in TransformStatement used to define language migrations (See Migrations)
You can also use patterns in your own languages.
Basically what happens is that a class is generated from a PatternExpression and the expression itself is reduced to a constructor of this class. This class extends GeneratedMatchingPattern and has a boolean method match(SNode), which returns a boolean value indicating whether the node matches the pattern. It also holds a method getFieldValue(Stirng) to get the values stored in pattern variables after a successful match.
So to develop your own language constructs using patterns, you can call these two methods in the generator template for your constructs.