MQL
Downloads
MQL can be obtained presently from a git repository only. In future, we will provide pre-compiled eclipse extensions.
Anonymous read-only access (cloning via HTTP takes a while, so please be patient!):
git clone http://build.se.informatik.uni-kiel.de/de.cau.se.measure.query.language.git
Read/write access:
git clone git@build.se.informatik.uni-kiel.de:de.cau.se.measure.query.language
Basic Grammar Structure
The basic structure of the grammar can be divided in fifth sections. First, the obligatory grammar header which imports usual terminal symbols for numbers, identifiers, strings and comments, followed by the used or generated meta-models and the grammar top and import rules. Second, the basic query syntax for MQL. Third, the expression syntax for data access. Fourth, the heart of the expression syntax. Fifth, the literals for both expression types. And fifth, some additional terminal symbols.
- languages/MQL/Grammar/DataExpressions
- languages/MQL/Grammar/Expressions
- languages/MQL/Grammar/FileHeader
- languages/MQL/Grammar/Literals
- languages/MQL/Grammar/Query
- languages/MQL/Grammar/Terminals
Data Expressions
/* Data expressions can only be used in selections to reference * fields of a result and do computations on them. */ DataExpression : Reference | Literal | FunctionCall | MeasureReference ; MeasureReference: reference=([mdl::Measure|SpecialName]) ('(' parameterAssignments+=DataExpression (',' parameterAssignments+=DataExpression)* ')')? ; ModelType: metamodel=[MeasuredModel|ID] '::' classifier=[ecore::EClassifier|ID] ;
Expressions
Expression: AndExpression ( ({Expression.left=current} operator='||') right=Expression)? ; AndExpression returns Expression: RelationalExpression ( ({Expression.left=current} operator='&&') right=AndExpression)? ; RelationalExpression returns Expression: AdditiveExpression ( ({Expression.left=current} operator=OpCompare) right=AdditiveExpression)?; OpCompare: '>=' | '<=' | '>' | '<' | '==' | '!=' ; AdditiveExpression returns Expression: MultiplicativeExpression (({Expression.left=current} operator=OpAdd) right=AdditiveExpression)?; OpAdd: '+' | '-'; MultiplicativeExpression returns Expression: UnaryOperation (({Expression.left=current} operator=OpMulti) right=MultiplicativeExpression)?; OpMulti: '*' | '**' | '/' | '%'; UnaryOperation returns Expression: {UnaryOperation} operator=OpUnary operand=PrimaryExpression | PrimaryExpression; OpUnary: "!" | "-" | "+"; PrimaryExpression returns PrimaryExpression: Literal | IfExpression | ForAllExpression | ExistsExpression | FunctionCall | ValueExpression | ModelType | ParenthesizedExpression; IfExpression: {IfExpression} 'if' '(' condition=Expression ')' then=Expression 'else' else=Expression ; ForAllExpression: {ForAllExpression} 'forall' '(' collection=Collection ('|' evaluate=Expression)? ')' ; ExistsExpression: {ExistsExpression} 'exists' '(' collection=Collection ('|' evaluate=Expression)? ')' ; Collection: name=ID 'in' collection=ValueExpression ; ParenthesizedExpression: '(' expression=Expression ')' ; FunctionCall: function=FunctionName '(' (parameterAssignments+=Expression (',' parameterAssignments+=Expression)*)? ')' ; enum FunctionName: ABS = 'abs' | FLOOR = 'floor' | CEIL = 'ceil' | SIZE = 'size' ; ValueExpression: base=ValueElement ('.' child=ValueExpression)? ; ValueElement: Reference | OperationCall | ReflectionCall ; Reference: reference=[ecore::EStructuralFeature|ID] ('[' selections+=Expression ']')* ; OperationCall: operation=[ecore::EOperation|ID] '(' (parameterAssignments+=Expression (',' parameterAssignments+=Expression)*)? ')' ; ReflectionCall: reflectionType=ReflectionType '(' type=[ecore::EClassifier|ID] ')' ; enum ReflectionType: IS_TYPE_OF = 'isTypeOf' | IS_KIND_OF = 'isKindOf' ;
File Header
Grammar Preamble
grammar de.cau.cs.se.measure.query.language.MeasureQueryLanguage with org.eclipse.xtext.common.Terminals generate query "http://se.cs.cau.de/languages/MeasureQueryLanguage" import "http://www.eclipse.org/emf/2002/Ecore" as ecore import "http://se.cs.cau.de/languages/MeasureDefinitionLanguage" as mdl
Grammar Service Structure
Model: (libraries+=Library)* (models+=MeasuredModel)* (queries+=Query)* ; // Import libraries defined in MDL files Library: 'import' importedNamespace = QualifiedNameWithWildcard ; MeasuredModel: 'model' name=ID package=[ecore::EPackage|STRING] ;
Literals
Literal: BooleanLiteral | IntLiteral | FloatLiteral | NullLiteral | StringLiteral | EnumerationExpression ; EnumerationExpression: (enumeration=[ecore::EEnum|ID])? '#' value=[ecore::EEnumLiteral|ID] ; IntLiteral: value=INT ; FloatLiteral: value=FLOAT ; BooleanLiteral: value=BOOLEAN ; NullLiteral: {NullLiteral} 'null'; StringLiteral: value=STRING ;
Query Composition
Query: selection=Select from=From condition=Where group=Group; Group: 'group' 'by' column=QualifiedName ; Select: 'select' selections+=Selection (',' selections+=Selection)* ; Selection returns ecore::EStructuralFeature: {Selection} data=DataExpression ('as' name=ID)? ; From: 'from' model=[MeasuredModel|ID] ; Where: 'where' expression=Expression ;
Terminals
Integers and identifiers and strings are already present through the Xtext terminals grammar. The only missing terminal are boolean values, which are represented by the word true and false.
terminal BOOLEAN returns ecore::EBooleanObject : "true" | "false";
Qualified names are sequences of IDs. Such names could either be composed through grammar rules, which would lead to complex models, or they could be seen as a token and therefore be interpreted by a resolver. The following QualifiedName rule realizes this second approach, which results in smaller models, as the model only requires a reference from the last named object in the ID-chain of the qualified name.
QualifiedName: ID (=>'.' ID)*;
To support the import of more than one class at once, the following rule defines a wildcard mechanism.
QualifiedNameWithWildcard: QualifiedName ('.' '*')? ;
Measures and other identifiable objects can have IDs or STRINGs to identify them. While the ID might be the preferred way, some external defined measures require path like identifiers, which can only be represented by strings. The token rule SpecialName is designed to address this issue.
SpecialName: ID | STRING ;
As expressions require integer and float values, the MQL grammar provides a rule for FLOATs. Important for floats, they must have always a decimal-point.
FLOAT: INT'.'INT ;
Releated Work and Used Technology
Object Constraint Language
The Object Constraint Language (OCL) is a formal language to describe expressions on UML models. It can be used to modify, reason or query UML and EMF-models. OCL is used in SMM to describe scopes over the meta-model where the measures are defined for. OCL plays a role in MDL in two ways. First, MDL is used to generate SMM models, which incorporate scope descriptions in OCL. Therefore, MDL must be able to generate these expressions. And second, MDL incorporates an expression notation to describe these scopes. Features and ideas from OCL can be found in that expression language.
XPath
The XML Path Language (XPath) is another model query language, with similarities to OCL. XPath is only able to query XML-DOM-models and is used in XPointer and XSLT to find nodes, node-sets and attributes. XSLT uses it in DOM-model transformations.
Eclipse Modeling Framework
A meta-modeling framework.
Xtext
A DSL modeling framework and toolchain.