sq/grammar/SLQ.g4
2020-08-06 11:58:47 -06:00

184 lines
3.1 KiB
ANTLR

grammar SLQ;
// "@mysql_db1 | .user, .address | join(.user.uid == .address.uid) | .[0:3] | .uid, .username, .country"
stmtList
: ';'* query ( ';'+ query )* ';'*
;
query: segment ('|' segment)* ;
segment: (element) (',' element)* ;
element: dsTblElement | dsElement | selElement | join | group | rowRange | fn | expr;
cmpr: LT_EQ | LT | GT_EQ | GT | EQ | NEQ ;
//whereExpr
// : expr
// ;
fn: fnName '(' ( expr ( ',' expr )* | '*' )? ')';
join
: ('join'|'JOIN'|'j')
'(' joinConstraint ')'
;
joinConstraint
: SEL cmpr SEL // .user.uid == .address.userid
| SEL // .uid
;
group
: ('group'|'GROUP'|'g')
'(' SEL (',' SEL)* ')'
;
selElement: SEL;
dsTblElement: DATASOURCE SEL; // data source table element, e.g. @my1.user
dsElement: DATASOURCE; // data source element, e.g. @my1
// [] select all rows
// [10] select row 10
// [10:15] select rows 10 thru 15
// [0:15] select rows 0 thru 15
// [:15] same as above (0 thru 15)
// [10:] select all rows from 10 onwards
rowRange
: '.['
( NN COLON NN // [10:15]
| NN COLON // [10:]
| COLON NN // [:15]
| NN // [10]
)? ']'
;
fnName
: 'sum' | 'SUM'
| 'avg' | 'AVG'
| 'count' | 'COUNT'
| 'where' | 'WHERE'
;
expr
: SEL
| literal
| unaryOperator expr
| expr '||' expr
| expr ( '*' | '/' | '%' ) expr
| expr ( '+' | '-' ) expr
| expr ( '<<' | '>>' | '&' ) expr
| expr ( '<' | '<=' | '>' | '>=' ) expr
| expr ( '==' | '!=' | ) expr
| expr '&&' expr
| fn
// | fnName '(' ( expr ( ',' expr )* | '*' )? ')'
;
literal
: NN
| NUMBER
| STRING
| NULL
;
unaryOperator
: '-'
| '+'
| '~'
| '!'
;
ID: [a-zA-Z_][a-zA-Z0-9_]* ;
WS : [ \t\r\n]+ -> skip ;
LPAR : '(' ;
RPAR: ')';
LBRA: '[' ;
RBRA: ']';
COMMA: ',';
PIPE: '|' ;
COLON: ':';
NULL: 'null' | 'NULL';
NN: INTF; // NN: Natural Number {0,1,2,3, ...}
NUMBER
: NN
| '-'? INTF '.' [0-9]+ EXP? // 1.35, 1.35E-9, 0.3, -4.5
| '-'? INTF EXP // 1e10 -3e4
| '-'? INTF // -3, 45
;
fragment INTF : '0' | [1-9] [0-9]* ; // no leading zeros
fragment EXP : [Ee] [+\-]? INTF ; // \- since - means "range" inside [...]
LT_EQ : '<=';
LT : '<';
GT_EQ : '>=';
GT : '>';
NEQ : '!=';
EQ : '==';
SEL: '.' ID ('.' ID)*; // SEL can be .THING or .THING.OTHERTHING etc.
DATASOURCE: '@' ID; // DS (Data Source): @mydb1 or @postgres_db2 etc.
STRING : '"' (ESC | ~["\\])* '"' ;
fragment ESC : '\\' (["\\/bfnrt] | UNICODE) ;
fragment UNICODE : 'u' HEX HEX HEX HEX ;
fragment HEX : [0-9a-fA-F] ;
//NUMERIC_LITERAL
// : DIGIT+ ( '.' DIGIT* )? ( E [-+]? DIGIT+ )?
// | '.' DIGIT+ ( E [-+]? DIGIT+ )?
// ;
fragment DIGIT : [0-9];
fragment A : [aA];
fragment B : [bB];
fragment C : [cC];
fragment D : [dD];
fragment E : [eE];
fragment F : [fF];
fragment G : [gG];
fragment H : [hH];
fragment I : [iI];
fragment J : [jJ];
fragment K : [kK];
fragment L : [lL];
fragment M : [mM];
fragment N : [nN];
fragment O : [oO];
fragment P : [pP];
fragment Q : [qQ];
fragment R : [rR];
fragment S : [sS];
fragment T : [tT];
fragment U : [uU];
fragment V : [vV];
fragment W : [wW];
fragment X : [xX];
fragment Y : [yY];
fragment Z : [zZ];
LINECOMMENT: '//' .*? '\n' -> skip ;