You can use these precedence rules when writing OCL expressions in MDriven to predict which parts of an expression are evaluated first and to make constraints, derivations, and ViewModel expressions unambiguous.
What precedence means
Operator precedence determines the order in which OCL evaluates operators when an expression has no parentheses. Operators nearer the top of the following table bind more tightly than operators below them.
For example, OCL evaluates -3 + 2 as (-3) + 2, because unary minus has higher precedence than addition. The result is -1.
Use parentheses ( and ) when you need a different evaluation order or when parentheses make the intended rule clearer.
MDriven OCL precedence order
The following order is specific to MDriven OCL. The first row has the highest precedence; the last row has the lowest.
| Precedence | Operators or expression form | Example | How the example is read |
|---|---|---|---|
| Highest | Dot and arrow navigation: . and ->
|
self.salary.sum()
|
Navigate from self to salary, then invoke sum().
|
Unary not and unary minus -
|
not self.age >= 18
|
Apply not before the comparison: (not self.age) >= 18. Use parentheses when combining not with comparisons to state your intended condition explicitly.
| |
Multiplication and division: * and /
|
2 + 3 * 4
|
2 + (3 * 4), which is 14.
| |
Addition and binary subtraction: + and -
|
10 - 3 + 2
|
The addition and subtraction are at the same level; write parentheses if the grouping matters. | |
Conditional expression: if ... then ... else ... endif
|
if self.age >= 18 then 'Adult' else 'Minor' endif
|
Evaluate the condition, then return the applicable branch. | |
Logical operators: and, or, and xor
|
self.age >= 18 and self.name <>
|
Evaluate the comparisons before applying and.
| |
implies
|
self.age >= 18 implies self.name <>
|
Evaluate each comparison, then apply implies.
| |
Relational comparisons: <, >, <=, and >=
|
self.age + 1 >= 18
|
Calculate self.age + 1, then compare it with 18.
| |
| Lowest | Equality comparisons: = and <>
|
self.gender = 'Male' or self.gender = 'Female'
|
Apply or before the equality tests under MDriven precedence. Add parentheses to express the intended two comparisons.
|
Use parentheses to state intent
Parentheses override the precedence table. They also make complex Boolean conditions easier to review and maintain.
For example, write a two-value gender check as:
(self.gender = 'Male') or (self.gender = 'Female')Do not rely on a reader inferring the grouping from the precedence table. This is especially important when an expression combines equality operators with and, or, xor, or implies.
Arithmetic example
Without parentheses:
2 + 3 * 4MDriven evaluates multiplication first, so this is equivalent to:
2 + (3 * 4)To add first, write:
(2 + 3) * 4Navigation operations have the highest precedence. In this expression, OCL first gets the salary collection from self, invokes sum(), and then compares the result:
self.salary.sum() < 100000For collection navigation and operators such as select, see Documentation:Turnkey session 7: Expressions and Documentation:OCLOperators.
Boolean condition example
Use parentheses around each complete comparison when combining conditions:
(self.age >= 18) and (self.name <> '')This expression is suitable for a rule that requires an adult to have a non-empty name. It first evaluates each comparison and then combines the Boolean results with and.
MDriven behavior differs from standard OCL
MDriven's order is not identical to the current OCL standard. In standard OCL, and, or, xor, and implies have lower precedence than all comparison operators:
<,>,<=,>==and<>
In MDriven OCL, the logical operators and implies are evaluated before those comparison operators. Therefore, use parentheses whenever you combine logical and comparison operators. Parenthesized expressions make your intended grouping explicit and avoid relying on a precedence difference when adapting expressions from another OCL implementation.
Writing checklist
- Use parentheses to override the default order.
- Parenthesize each comparison when combining it with
and,or,xor, orimplies. - Keep navigation and collection operations close to the value they operate on, for example
self.salary.sum(). - Use unary minus only for a single value, for example
-3; see Documentation:OCLOperators unary-. - Test the expression in the OCL expression context where you will use it, such as a constraint, derived attribute, or ViewModel expression.
See also
- Documentation:OCL
- Documentation:Learn OCL
- Documentation:OCL Expressions
- Documentation:OCLOperators
- Documentation:Part 2 OCL: Operators
Worked examples: logical operators and comparisons
Worked examples: logical operators and comparisons
and, or, xor, and implies have higher precedence than relational and equality comparisons. Do not copy an unparenthesized expression from another OCL implementation. Parenthesize every comparison before combining Boolean conditions.Use these examples when you write OCL for a constraint, derivation, or ViewModel expression. The examples show evaluation order, not recommended unparenthesized syntax.
Example 1: Equality combined with or
Consider a rule intended to accept either of two gender values:
self.gender = 'Male' or self.gender = 'Female'| OCL implementation | Evaluation order |
|---|---|
| MDriven OCL | or has higher precedence than =, so MDriven applies or before the equality comparisons.
|
| Standard OCL | Each equality comparison has higher precedence than or, so the two comparisons are evaluated before or.
|
Write the intended rule explicitly:
(self.gender = 'Male') or (self.gender = 'Female')Example 2: Relational comparison combined with and
Consider a rule intended to require an adult with a non-empty name:
self.age >= 18 and self.name <> ''In MDriven OCL, and has higher precedence than both >= and <>. In standard OCL, the relational and equality comparisons have higher precedence than and.
Write each complete comparison in parentheses:
(self.age >= 18) and (self.name <> '')This form evaluates self.age >= 18 and self.name <> as Boolean conditions, then combines those Boolean results with and.
Example 3: Several comparisons combined with and and or
Consider this unparenthesized expression:
a > 5 and b > 10 or c < 3| OCL implementation | Evaluation order |
|---|---|
| MDriven OCL | The logical operators and and or have higher precedence than > and <.
|
| Standard OCL | The comparisons a > 5, b > 10, and c < 3 have higher precedence than the logical operators.
|
If the intended rule is to evaluate the three comparisons and then combine their Boolean results, write:
((a > 5) and (b > 10)) or (c < 3)The parentheses state both parts of the rule: a must be greater than 5 and b must be greater than 10, or c must be less than 3.
Example 4: A comparison combined with implies
Consider a rule where a condition implies a second condition:
self.age >= 18 implies self.name <> ''In MDriven OCL, implies has higher precedence than >= and <>. Standard OCL evaluates the comparisons before implies.
Write the Boolean operands of implies explicitly:
(self.age >= 18) implies (self.name <> '')Use this pattern whenever either side of implies contains a comparison. For the Boolean meaning of implies, see Documentation:OCLOperators Implies.
Examples
Examples
You can use these examples to see which operation MDriven OCL evaluates first and when you must add parentheses.
Arithmetic and comparison
In this expression, multiplication binds more tightly than addition, and addition binds more tightly than the relational comparison:
2 + 3 * 4 >= 14MDriven evaluates it as:
(2 + (3 * 4)) >= 14The arithmetic result is 14, so the comparison is true. To change the calculation, parenthesize the addition:
((2 + 3) * 4) >= 14Navigation and collection operations bind more tightly than a comparison. This expression gets the salary collection, invokes sum(), and then compares the result:
self.salary.sum() < 100000It is equivalent to:
(self.salary.sum()) < 100000For more collection-operation examples, see Documentation:OCLOperators and Documentation:Turnkey session 7: Expressions.
A condition with two comparisons
Write each comparison as a parenthesized Boolean value before combining the values with and or or:
(self.age >= 18) and (self.name <> '')This condition first determines whether self.age is at least 18 and whether self.name is not empty. It then applies and to those two Boolean results.
Do not write the condition without parentheses:
self.age >= 18 and self.name <> ''Under the MDriven precedence table, and binds more tightly than >= and <>. This differs from standard OCL, where the comparisons bind more tightly than and. Parentheses state the intended two comparisons in both implementations.
A two-value equality check
Use parentheses around each equality comparison when testing alternative values:
(self.gender = 'Male') or (self.gender = 'Female')This evaluates each equality comparison and then applies or. Without the parentheses:
self.gender = 'Male' or self.gender = 'Female'MDriven gives or higher precedence than =; standard OCL gives = higher precedence than or. Use the parenthesized form so that the rule remains explicit when you use it in a constraint, derivation, or ViewModel expression.
Unary minus with arithmetic
Unary minus binds more tightly than addition. MDriven evaluates:
-3 + 2as:
(-3) + 2The result is -1. To negate the sum instead, write:
-(3 + 2)See Documentation:OCLOperators unary- for more unary-minus examples.
