grammar KGSQL;
/**
* Knowledge Graph System Query Language ANTLR4 Grammar.
*/
@header {
package kgsql.parser;
}
root : command;
command : prologue ( selectQuery | askQuery
| constructQuery | insertRequest | deleteRequest );
prologue : prefixDecl*;
prefixDecl : Prefix NameSpace Identifier;
selectQuery : Select Variable+ whereClause;
askQuery : Ask whereClause;
constructQuery : Construct patternBlock whereClause;
insertRequest : Insert patternBlock whereClause;
deleteRequest : Delete Variable+ whereClause;
whereClause : Where?
'{' patternBlock? ( filter '.'? patternBlock? )* '}';
patternBlock : patternsSameSubject ( '.' patternBlock? )?;
filter : Filter constraint;
patternsSameSubject : ( noun | linkedList ) predicateList?;
predicateList : verb objectList ( ';' ( verb objectList )? )*;
objectList : object ( ',' object )*;
object : noun | linkedList;
noun : resourceOrVariable multiplicity?
| '[' resourceOrVariable resourceOrVariable? typeUnion ']' multiplicity?;
verb : typeUnion multiplicity? | '[' resourceOrVariable typeUnion ']' multiplicity?;
typeUnion : Variable | prefixedName ( '|' prefixedName )*;
resourceOrVariable : prefixedName | typedLiteral | numericLiteral | True | False | Variable;
linkedList : '(' ( resourceOrVariable | linkedList )* ')'
| '[' '(' ( resourceOrVariable | linkedList )* ')' prefixedName ']';
prefixedName : NameSpace LocalName;
constraint : '(' expression ')' | LocalName '(' expressionList? ')';
expressionList : expression ( ',' expression )*;
expression : conditionalAndExpression ( '||' conditionalAndExpression )*;
conditionalAndExpression : relationalExpression ( '&&' relationalExpression )*;
relationalExpression : additiveExpression ( '=' additiveExpression | '!=' additiveExpression
| '<' additiveExpression | '>' additiveExpression
| '<=' additiveExpression | '>=' additiveExpression )?;
additiveExpression : multiplicativeExpression ('+' multiplicativeExpression
| '-' multiplicativeExpression | NatPositive | NatNegative | RealPositive | RealNegative )*;
multiplicativeExpression : unaryExpression ( '*' unaryExpression | '/' unaryExpression )*;
unaryExpression : primaryExpression | '+' primaryExpression | '-' primaryExpression | '!' primaryExpression;
primaryExpression : '(' expression ')' | LocalName '(' expressionList? ')' | resourceOrVariable | askQuery;
typedLiteral : Literal Lang? | '[' Literal Lang? prefixedName ']' | Literal Lang? '^^' prefixedName;
numericLiteral : Nat | NatPositive | NatNegative | UnsignedReal | RealPositive | RealNegative;
multiplicity : '{' integer '}' | '{' integer '..' integer '}';
integer : Nat | NatPositive | NatNegative | '*';
// Lexical Scanner Tokens
// In general, KGSQL is case-sensitive,
// but the following reserved words are case-insensitive:
Prefix : [Pp][Rr][Ee][Ff][Ii][Xx] WS;
Select : [Ss][Ee][Ll][Ee][Cc][Tt] WS;
Ask : [Aa][Ss][Kk] WS;
Construct : [Cc][Oo][Nn][Ss][Tt][Rr][Uu][Cc][Tt] WS;
Insert : [Ii][Nn][Ss][Ee][Rr][Tt] WS;
Delete : [Dd][Ee][Ll][Ee][Tt][Ee] WS;
Where : [Ww][Hh][Ee][Rr][Ee];
Filter : [Ff][Ii][Ll][Tt][Ee][Rr];
True : [Tt][Rr][Uu][Ee];
False : [Ff][Aa][Ll][Ss][Ee];
// Identifiers
// The forbidden characters in an identifier are: spaces " < > \ ^ ` { | }
Identifier : '<' (~[\u0000-\u0020\u0022\u003C\u003E\u005C\u005E\u0060\u007B\u007C\u007D])* '>';
// Language Codes
Lang : '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)*;
// Numbers
fragment UnsignedDecimal : [0-9]+ '.' [0-9]+? | '.' [0-9]+;
fragment Exponent : [eE] [+-]? [0-9]+;
fragment UnsignedDouble : [0-9]+ '.' [0-9]+? Exponent | '.' [0-9]+ Exponent | [0-9]+ Exponent;
Nat : [0-9]+;
NatPositive : '+' Nat;
NatNegative : '-' Nat;
UnsignedReal : UnsignedDecimal | UnsignedDouble;
RealPositive : '+' UnsignedReal;
RealNegative : '-' UnsignedReal;
// String Literals
fragment EscapedCharacter : '\\' [tbnrf'"];
fragment StringLiteral1 : '\'' ( (~[\u0027\u005C\u000A\u000D]) | EscapedCharacter )* '\'';
fragment StringLiteral2 : '"' ( (~[\u0022\u005C\u000A\u000D]) | EscapedCharacter )* '"';
Literal : StringLiteral1 | StringLiteral2;
// Names
fragment CharsBase : [A-Z] | [a-z] | [\u00C0-\u00D6] | [\u00D8-\u00F6] | [\u00F8-\u02FF]
| [\u0370-\u037D] | [\u037F-\u1FFF] | [\u200C-\u200D] | [\u2070-\u218F] | [\u2C00-\u2FEF]
| [\u3001-\uD7FF] | [\uF900-\uFDCF] | [\uFDF0-\uFFFD];
fragment CharsU : CharsBase | '_';
fragment VarName : ( CharsU | [0-9] ) ( CharsU | [0-9] | [\u00B7] | [\u0300-\u036F] | [\u203F-\u2040] )*;
fragment Chars : CharsU | '-' | [0-9] | [\u00B7] | [\u0300-\u036F] | [\u203F-\u2040];
fragment PrefixName : CharsBase ( ( Chars | '.' )* Chars )?;
NameSpace : ':' | PrefixName ':';
LocalName : ( CharsU | [0-9] ) ( ( Chars | '.' )* Chars )?;
Variable : ( '?' | '$' ) VarName;
// Whitespace
fragment WS : (' '|'\t'|'\n'|'\r')+;
S : WS -> skip;