TQL-Grammatik und EBNF-Notation
Die Tosca Query Language (TQL) ist eine formale Sprache. Such-Abfragen müssen also mithilfe einer formalen Grammatik gebildet werden, um vom System verstanden zu werden.
Der Aufbau besteht aus sogenannten Nonterminalen und Terminalen. Nonterminale sind Ausdrücke, die wiederum durch andere Ausdrücke (Nonterminale oder Terminale) ersetzt werden können.
Terminale stellen atomare Elemente dar und können nicht durch andere Ausdrücke ersetzt werden. Eine korrekte Query, die von TQL verstanden wird, muss aus einer Folge von Terminalen bestehen. Um also einen gültigen Suchausdruck erstellen zu können, werden sukzessive alle Nonterminale so ersetzt, dass am Ende der gewünschte Suchausdruck, bestehend aus Terminalen, herauskommt.
Für die Beschreibung der Grammatik der TQL wird die EBNF-Notation verwendet (siehe Kapitel "EBNF-Notation").
EBNF-Notation
Hilfreich ist hierbei, dass Nonterminale in TQL immer mit einem Kleinbuchstaben beginnen. Terminale sind entweder ein Sonderzeichen (z.B.: „]“ , „)“, „:“ ), oder beginnen mit einem Großbuchstaben.
TQL-Grammatik
Eine Grammatik besteht aus so genannten Produktionen. Dabei handelt es sich um Regeln, mit denen Nonterminale durch andere Nonterminale und Terminale ersetzt werden können. Eine Abfrage muss aus einer Folge von Terminalen bestehen. Um einen gültigen Suchausdruck zu bilden, müssen alle Nonterminale durch Terminale ersetzt werden:
![]() |
query: = {arrowOperator [returnToken] searchExpression} |
Die oben angegebene Produktion besteht aus den Nonterminalen query, arrowOperator, returnToken und searchExpression (Anmerkung: alle beginnen mit einem Kleinbuchstaben). Der returnToken ist optional und arrowOperator [returnToken] searchExpression kann, wegen der geschwungenen Klammern, beliebig oft aneinander gereiht werden.
Eine Grammatik besteht aus einer Menge von Produktionen, die von oben nach unten abgearbeitet werden. Man beginnt mit einem Startsymbol bestehend aus einem Nonterminal und ersetzt dieses solange, bis eine Such-Query bestehend aus Terminalen übrig bleibt.
Vollständige TQL-Grammatik
Startsymbol : query
query |
::= { arrowOperator [ returnToken ] searchExpression } |
|
searchExpression |
::= ( assocName | aggregation | specialAssocName | setOperation | subsetOperation | sortOperation | objectsSelector ) [ colonToken type ] [ leftSquareBracket logicalExpression rightSpareBracket ] |
|
logicalExpression |
::= ( notToken logicalExpression ) | leftParenthesis logicalExpression rightParenthesis | comparisionExpression { logicalOperator logicalExpression } |
|
comparisonExpression |
::= expression compOperator expression |
|
expression |
::= term {addOperator term} |
Dieser Term kann durch ein stringLiteral, intLiteral, ein Attribut oder einen Wert ersetzt werden |
term |
::= factor {mulOperator factor} |
|
factor |
::= leftParenthesis expression rightParenthesis | functionStatement | value |
|
functionStatement |
::= functionName leftParenthesis [ expression { comma expression } ] rightParenthesis |
|
value |
::= stringLiteral| intLiteral| attribute |
|
attribut |
::= {assocName pointToken} identifier |
|
assocName |
::= identifier |
Der assocName wird durch einen Bezeichner (identifier) ersetzt |
type |
::= identifier |
Durch die Angabe des Typs, wird festgelegt nach welchem Objekt in der entsprechenden Query gesucht werden soll. |
::= doublequote TEXT doublequote |
TEXT stellt einen Platzhalter für beliebige Zeichenfolgen dar. Für Sonderzeichen muss ein umgekehrter Schrägstrich (Backslash) als Escape-Zeichen verwendet werden. Mehrere Sonderzeichen im Text können übernommen werden, indem die Zeichenkette durch Hochkomma ['] begrenzt wird. | |
intLiteral |
::= [ "+" | "-" ] DIGITS |
|
uintLiteral |
::= DIGITS |
|
identifier |
::= (LETTER | "_") {LETTER | DIGIT | "_"} | quote TEXT quote |
|
aggregation |
::= "SUBPARTS" | "SUPERPART" | "SELF" | "PROJECT" |
|
specialAssocName |
::= "AllReferences" | "OwningObject" |
|
setOperation |
::= setFunction leftParenthesis search {comma search}] rightParenthesis |
|
setFunction |
::= "COMPLEMENT" | "UNION" | "INTERSECTION" |
|
sortOperation |
::= sortFunction leftParenthesis search {comma stringLiteral}] rightParenthesis |
|
sortFunction |
::= "SORT" |
|
objectsSelector |
::= "OBJECTS" leftParenthesis uniqueIdOrNodePath {comma uniqueIdOrNodePath}] rightParenthesis |
|
uniqueIdOrNodePath |
::= uniqueIdString | nodePathString |
|
uniqueIdString |
::= stringLiteral |
|
nodePathString |
::= stringLiteral |
|
subsetOperation |
::= "SUBSET" leftParenthesis intLiteral [comma uintLiteral]] rightParenthesis |
|
arrowOperator |
:= "=>" | "->" |
|
compOperator |
::= "==" | "!=" | "=i=" | "!i=" | ">" | "<" | ">=" | "<=" | "=?" | "=i?" | "!?" | "!i?" | // LIKE "=*" // LIKE (old version) "=~" | "=i~" // REGEX |
compOperatoren werden verwendet, um zwei Ausdrücke miteinander zu verknüpfen und einen logischen Wert (true, false) zu ermitteln. |
logicalOperator |
::= "AND" | "OR" |
conjunction, disjunction |
addOperator |
::= "+" | "-" |
|
mulOperator |
::= "*" | "/" |
|
returnToken |
::= "RETURN" |
|
notToken |
::= "NOT" |
mit dem notToken ist es möglich, einen logischen Ausdruck zu negieren |
pointToken |
::= "." |
|
colonToken |
::= ":" |
|
leftSquareBracket |
::= "[" |
stellt eine öffnende, eckige Klammer dar |
rightSquareBracket |
::= "]" |
stellt eine schließende, eckige Klammer dar |
leftParenthesis |
::= "(" |
stellt eine öffnende, runde Klammer dar |
rightParenthesis |
::= ")" |
stellt eine schließende, runde Klammer dar |
comma |
::= "," |
|
quota |
::= "'" |
|
doubleQuote |
::= "“" |
|
quantifierOperator |
::= '<ANY>' |
gibt alle Objekte zurück, in denen der angegebene Wert vorkommt. |