Actions

Ontolog Forum

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 triplesBlock whereClause;

insertRequest : Insert triplesBlock whereClause;

deleteRequest : Delete Variable+ whereClause;

whereClause : Where? 
  '{' triplesBlock? ( filter '.'? triplesBlock? )* '}';

triplesBlock : triplesSameSubject ( '.' triplesBlock? )?;

filter : Filter constraint;

triplesSameSubject : ( 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;