sq/grammar/SLQ.g4

152 lines
2.9 KiB
Plaintext
Raw Normal View History

2016-10-17 07:14:01 +03:00
grammar SLQ;
// "@mysql_db1 | .user, .address | join(.user.uid == .address.uid) | .[0:3] | .uid, .username, .country"
stmtList: ';'* query ( ';'+ query)* ';'*;
2016-10-17 07:14:01 +03:00
query: segment ('|' segment)*;
2016-10-17 07:14:01 +03:00
segment: (element) (',' element)*;
2016-10-17 07:14:01 +03:00
element:
dsTblElement
| dsElement
| selElement
| join
| group
| rowRange
| fn
| expr;
2016-10-17 07:14:01 +03:00
cmpr: LT_EQ | LT | GT_EQ | GT | EQ | NEQ;
2016-10-17 07:14:01 +03:00
2020-08-06 20:58:47 +03:00
//whereExpr
// : expr ;
2016-10-17 07:14:01 +03:00
fn: fnName '(' ( expr ( ',' expr)* | '*')? ')';
2020-08-06 20:58:47 +03:00
join: ('join' | 'JOIN' | 'j') '(' joinConstraint ')';
2020-08-06 20:58:47 +03:00
joinConstraint:
SEL cmpr SEL // .user.uid == .address.userid
| SEL ; // .uid
2020-08-06 20:58:47 +03:00
group: ('group' | 'GROUP' | 'g') '(' SEL (',' SEL)* ')';
2020-08-06 20:58:47 +03:00
2016-10-17 07:14:01 +03:00
selElement: SEL;
2016-10-31 01:35:56 +03:00
dsTblElement:
DATASOURCE SEL; // data source table element, e.g. @my1.user
2020-08-06 20:58:47 +03:00
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: '(';
2016-10-17 07:14:01 +03:00
RPAR: ')';
LBRA: '[';
2016-10-17 07:14:01 +03:00
RBRA: ']';
COMMA: ',';
PIPE: '|';
2016-10-17 07:14:01 +03:00
COLON: ':';
NULL: 'null' | 'NULL';
2020-08-06 20:58:47 +03:00
NN: INTF; // NN: Natural Number {0,1,2,3, ...}
2016-10-17 07:14:01 +03:00
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];
2020-08-06 20:58:47 +03:00
//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;