// KerML Expression Sub-language
// Shared expression grammar used by both KerML and SysML parsers
// Per SysML v2.0 spec section 8.1: SysML uses "the full KerML expression sub-language"
// Reference: https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation/blob/master/org.omg.kerml.expressions.xtext
//
// ARCHITECTURE:
// This file defines the complete expression precedence chain from OwnedExpression
// down to UnaryExpression, including all _Member and _Reference wrapper rules
// that are used for AST construction.
//
// EXTENSION POINTS (must be defined in each grammar):
// - classification_expression: Handles type classification operators (@ @@ as meta hastype istype)
// - extent_expression: Handles 'all' operator and collection operations
// - primary_expression: Handles literals, invocations, feature references, parenthesized expressions
//
// TOKEN DEPENDENCIES (must be defined in each grammar):
// - if_token, else_token, question_mark, double_question_mark
// - implies_token, or_token, xor_token, and_token, not_token
// - equality_operator, relational_operator
// - additive_operator, multiplicative_operator, exponentiation_operator, unary_operator
// =============================================================================
// EXPRESSION PRECEDENCE CHAIN (per KerMLExpressions.xtext)
// OwnedExpression → ConditionalExpression → ... → UnaryExpression → ExtentExpression
// =============================================================================
// OwnedExpressionMember - wraps OwnedExpression for membership context
owned_expression_member = { owned_expression }
// OwnedExpression - entry point for value expressions
owned_expression = { conditional_expression }
// OwnedExpressionReference - reference wrapper used in conditional branches
owned_expression_reference = { owned_expression_member }
// -----------------------------------------------------------------------------
// CONDITIONAL EXPRESSION (if-then-else ternary)
// if condition ? then_expr else else_expr
// -----------------------------------------------------------------------------
conditional_expression = {
if_token ~ null_coalescing_expression ~ question_mark ~ owned_expression_reference ~ else_token ~ owned_expression_reference
| null_coalescing_expression
}
// -----------------------------------------------------------------------------
// NULL COALESCING EXPRESSION: expr ?? default
// -----------------------------------------------------------------------------
null_coalescing_expression = {
implies_expression ~ (double_question_mark ~ implies_expression_reference)*
}
// -----------------------------------------------------------------------------
// LOGICAL EXPRESSIONS
// -----------------------------------------------------------------------------
// Implication: a implies b
implies_expression_member = { implies_expression }
implies_expression_reference = { implies_expression_member }
implies_expression = {
or_expression ~ (implies_token ~ or_expression_reference)*
}
// OR: a or b, a | b
or_expression_member = { or_expression }
or_expression_reference = { or_expression_member }
or_expression = {
xor_expression ~ ((or_token ~ xor_expression_reference) | ("|" ~ xor_expression))*
}
// XOR: a xor b
xor_expression_member = { xor_expression }
xor_expression_reference = { xor_expression_member }
xor_expression = {
and_expression ~ (xor_token ~ and_expression)*
}
// AND: a and b, a & b
and_expression = {
equality_expression ~ ((and_token ~ equality_expression_reference) | ("&" ~ equality_expression))*
}
// -----------------------------------------------------------------------------
// EQUALITY EXPRESSION: a == b, a != b, a === b, a !== b
// -----------------------------------------------------------------------------
equality_expression_member = { equality_expression }
equality_expression_reference = { equality_expression_member }
equality_expression = {
classification_expression ~ (equality_operator ~ classification_expression)*
}
// NOTE: classification_expression must be defined in each grammar
// It handles type operators: @ @@ as meta hastype istype
// KerML and SysML have different operators here
// -----------------------------------------------------------------------------
// RELATIONAL EXPRESSION: a < b, a <= b, a > b, a >= b
// -----------------------------------------------------------------------------
relational_expression = {
range_expression ~ (relational_operator ~ range_expression)*
}
// -----------------------------------------------------------------------------
// RANGE EXPRESSION: a .. b
// -----------------------------------------------------------------------------
range_expression = {
additive_expression ~ (".." ~ additive_expression)?
}
// -----------------------------------------------------------------------------
// ARITHMETIC EXPRESSIONS
// -----------------------------------------------------------------------------
// Addition/subtraction: a + b, a - b
additive_expression = {
multiplicative_expression ~ (additive_operator ~ multiplicative_expression)*
}
// Multiplication/division: a * b, a / b, a % b
multiplicative_expression = {
exponentiation_expression ~ (multiplicative_operator ~ exponentiation_expression)*
}
// Exponentiation: a ** b, a ^ b (right associative)
exponentiation_expression = {
unary_expression ~ (exponentiation_operator ~ exponentiation_expression)?
}
// -----------------------------------------------------------------------------
// UNARY EXPRESSION: +a, -a, ~a, not a
// -----------------------------------------------------------------------------
unary_expression = {
unary_operator ~ extent_expression
| extent_expression
}
// NOTE: extent_expression must be defined in each grammar
// It handles: 'all' TypeRef, and leads to primary_expression
// Different grammars have different collect/select/index operations