Concrete Syntax


This section describes the concrete syntax of the OCL. This allows modelers to write down OCL expressions in a standardized way. A formal mapping from the concrete syntax to the abstract syntax from Chapter 8 ("Abstract Syntax") is given. Although not required by the UML 2.0 for OCL RFP, Section 9.6 describes a mapping from the abstract syntax  to the concrete syntax. This allows one to produce a standard human readable version of any OCL expression that is
represented as an instance of the abstract syntax.

Section 9.1 ("Structure of the Concrete Syntax") describes the structure of the grammar and the motivation for the use of  an attribute grammar.

Structure of the Concrete Syntax

The concrete syntax of OCL is described in the form of an a full attribute grammar. Each production in an attribute grammar may have synthesized attributes attached to it. The value of synthesized attributes of elements on the left hand side of a production rule is always derived from attributes of elements at the right hand side of that production rule. Each production may also have inherited attributes attached to it. The value of inherited attributes of elements on the right  hand side of a production rule is always derived from attributes of elements on the left hand side of that production.

In the attribute grammar that specifies the concrete syntax, every production rule is denoted using the EBNF formalism  and annotated with synthesised and inherited attributes, and disambiguating rules. There are a number of special annotations:

Synthesized attributes. Each production rule has one synthesized attribute called ast (short for abstract syntax tree), that holds the instance of the OCL Abstract Syntax that is returned by the rule. The type of ast is different for every rule, but it always is an element of the abstract syntax. The type is stated with each production rule under the heading "Abstract Syntax Mapping". The ast attribute constitutes the formal mapping from concrete syntax to abstract syntax.

The motivation for the use of an attribute grammar is the easiness of the construction and the clarity of this mapping. Note that each name in the EBNF format of the production rule is postfixed with 'CS' to clearly distinguish between the concrete syntax elements and their abstract syntax counterparts.

Inherited attributes. Each production rule has one inherited attribute called env (short for environment), that holds a list of names that are visible from the expression. All names are references to elements in the model. In fact, env is a name space environment for the expression or expression part denoted according to the production rule. The type of the env attribute is Environment, as shown in Figure 13 . A number of operations are defined for this type. Their
definitions and more details on the Environment type can be found in Section 9.4 ("Environment definition"). The manner  in which both the ast and env attributes are determined, is given using OCL expressions.

Note that the contents of the env attribute are fully determined by the context of the OCL expression. When an OCL  expression is used as an invariant to class X, its environment will be different than in the case the expression is used as a postcondition to an operation of class Y. In Chapter 12 ("The Use of Ocl Expressions in UML Models") the context of  OCL expressions is defined in detail.

Multiple production rules. For some elements there is a choice of multiple production rules. In that case the EBNF  format of each production rule is prefixed by a capital letter between square brackets. The same prefix is used for the  corresponding determination rules for the ast and env attributes.

Multiple occurences of production names. In some production rules the same element name is used more than once. To distinguish between these occurences the names will be postfixed by a number in square brackets, as in the following example.

CollectionRangeCS ::= OclExpressionCS[1] '..' OclExpressionCS[2]

Disambiguating rules. Some of the production rules are syntactically ambiguous. For such productions disambiguating  rules have been defined. Using these rules, each production and thus the complete grammar becomes nonambiguous. For example in parsing a.b(), there are at least three possible parsing solutions:

  1.   a is a VariableExpr (a reference to a let or an iterator variable)
  2.   a is an AttributeCallExp (self is implicit)
  3.   a is a NavigationCallExp (self is implicit)
A decision on which grammar production rule to use, can only be made when the environment of the expression is taken  into account. The disambiguating rules describe these choices based on the environment and allow unambiguous parsing of a.b(). In this case the rules (in plain English) would be:
 
Disambiguating rules may be based on the UML model to which the OCL expresion is attached (e.g does an attribute exist or not). Because of this, the UML model must be available when an OCL expression is parsed, otherwise it cannot be validated as a correct expression. The grammar is structured in such a way that at most one of the production rules will fullfil all the disambiguating rules, thus ensuring that the grammar as a whole is unambiguous. The disambiguating rules are written in OCL, and use some metaclasses and additional operations from the UML 1.4 semantics.