1//https://github.com/antlr/grammars-v4/
2
3grammar PageSql;
4
5
6/**
7 Lexer (ie token)
8 https://github.com/antlr/antlr4/blob/master/doc/lexer-rules.md
9*/
10SCOL:      ';';
11DOT:       '.';
12LPAREN:  '(';
13RPAREN: ')';
14LSQUARE:  '[';
15RSQUARE: ']';
16LCURLY: '{';
17RCURLY: '}';
18COMMA:     ',';
19BITWISEXOR : '^';
20DOLLAR : '$';
21EQUAL:    '=';
22STAR:      '*';
23PLUS:      '+';
24MINUS:     '-';
25TILDE:     '~';
26PIPE2:     '||';
27DIV:       '/';
28MOD:       '%';
29LT2:       '<<';
30GT2:       '>>';
31AMP:       '&';
32PIPE:      '|';
33QUESTION:  '?';
34LESS_THAN:        '<';
35LESS_THAN_OR_EQUAL:     '<=';
36GREATER_THAN:        '>';
37GREATER_THAN_OR_EQUAL:     '>=';
38EQ:        '==';
39NOT_EQUAL:   '!=';
40NOT_EQ2:   '<>';
41
42/**
43 * Key word
44*/
45AND:               A N D;
46AS:                A S;
47ASC:               A S C;
48BETWEEN:           B E T W E E N;
49BY:                B Y;
50DESC:              D E S C;
51ESCAPE:            E S C A P E;
52FALSE:             F A L S E;
53FROM:              F R O M;
54GLOB:              G L O B;
55IN:                I N;
56IS:                I S;
57ISNULL:            I S N U L L;
58LIKE:              L I K E;
59LIMIT:             L I M I T;
60NOT:               N O T;
61NOTNULL:           N O T N U L L;
62NOW:               N O W;
63NULL:              N U L L;
64OR:                O R;
65ORDER:             O R D E R;
66SELECT:            S E L E C T;
67TRUE:              T R U E;
68WHERE:             W H E R E;
69RANDOM:            R A N D O M;
70
71// Function
72DATE:            D A T E;
73DATETIME:        D A T E T I M E;
74functionNames: DATE | DATETIME;
75
76// constant
77constantNames: NOW;
78
79// Tables
80PAGES:            P A G E S;
81BACKLINKS:        B A C K L I N K S;
82DESCENDANTS:       D E S C E N D A N T S;
83tableNames: PAGES | BACKLINKS | DESCENDANTS;
84
85// LITERALS
86fragment Letter : 'a'..'z' | 'A'..'Z';
87
88fragment HexDigit : 'a'..'f' | 'A'..'F';
89
90fragment Digit : '0'..'9' ;
91
92fragment Exponent : ('e' | 'E') ( PLUS|MINUS )? (Digit)+;
93
94fragment RegexComponent :
95    'a'..'z' | 'A'..'Z' | '0'..'9' | '_'
96    | PLUS | STAR | QUESTION | MINUS | DOT
97    | LPAREN | RPAREN | LSQUARE | RSQUARE | LCURLY | RCURLY
98    | BITWISEXOR | PIPE | DOLLAR | '!'
99    ;
100
101// https://www.sqlite.org/lang_expr.html
102// A string constant is formed by enclosing the string in single quotes ('). A single quote within the string can be encoded by putting two single quotes in a row - as in Pascal. C-style escapes using the backslash character are not supported because they are not standard SQL.
103StringLiteral :
104    ( '\'' ( ~'\'' | '\'\'')* '\''
105    | '"' ( ~('"') )* '"'
106    )+
107    ;
108
109CharSetLiteral
110    : StringLiteral
111    | '0' 'X' (HexDigit|Digit)+
112    ;
113
114IntegralLiteral
115    : (Digit)+ ('L' | 'S' | 'Y')
116    ;
117
118Number
119    : (Digit)+ ( DOT (Digit)* (Exponent)? | Exponent)?
120    ;
121
122NumberLiteral
123    : Number ('D' | 'B' 'D')
124    ;
125
126ByteLengthLiteral
127    : (Digit)+ ('b' | 'B' | 'k' | 'K' | 'm' | 'M' | 'g' | 'G')
128    ;
129
130
131/**
132 * Sql also does not permit
133 * to start with a number
134 * (just ot have no conflict with a NUMERIC_LITERAL)
135*/
136SqlName: (Letter | Digit) (Letter | Digit | '_')*;
137
138
139/**
140* Space are for human (discard)
141*/
142SPACES: [ \u000B\t\r\n] -> channel(HIDDEN);
143
144
145
146/**
147 * Fragment rules does not result in tokens visible to the parser.
148 * They aid in the recognition of tokens.
149*/
150
151fragment HEX_DIGIT: [0-9a-fA-F];
152fragment INTEGER_LITERAL: Digit+;
153fragment NUMERIC_LITERAL: Digit+ ('.' Digit*)?;
154fragment ALL_LITERAL_VALUE: StringLiteral | INTEGER_LITERAL | NUMERIC_LITERAL | NULL | TRUE
155   | FALSE
156   | NOW;
157
158
159fragment ANY_NAME: SqlName | StringLiteral | LPAREN ANY_NAME RPAREN;
160fragment A: [aA];
161fragment B: [bB];
162fragment C: [cC];
163fragment D: [dD];
164fragment E: [eE];
165fragment F: [fF];
166fragment G: [gG];
167fragment H: [hH];
168fragment I: [iI];
169fragment J: [jJ];
170fragment K: [kK];
171fragment L: [lL];
172fragment M: [mM];
173fragment N: [nN];
174fragment O: [oO];
175fragment P: [pP];
176fragment Q: [qQ];
177fragment R: [rR];
178fragment S: [sS];
179fragment T: [tT];
180fragment U: [uU];
181fragment V: [vV];
182fragment W: [wW];
183fragment X: [xX];
184fragment Y: [yY];
185fragment Z: [zZ];
186
187/**
188 * Parser (ie structure)
189 * https://github.com/antlr/antlr4/blob/master/doc/parser-rules.md
190*/
191
192sqlNames : SqlName|Number;
193
194column: sqlNames (DOT sqlNames)? (AS (sqlNames|StringLiteral))?;
195
196pattern: (StringLiteral|NumberLiteral);
197
198
199expression:
200    (SqlName|StringLiteral|NumberLiteral|Number|constantNames)
201    | functionNames LPAREN expression? ( COMMA expression)* RPAREN
202;
203
204predicate: sqlNames
205    (
206        (( LESS_THAN | LESS_THAN_OR_EQUAL | GREATER_THAN | GREATER_THAN_OR_EQUAL | NOT_EQUAL | EQUAL) expression)
207        |
208        (
209            NOT?
210            (LIKE pattern (ESCAPE StringLiteral)?)
211            |
212            (GLOB pattern)
213        )
214        |
215        (NOT? BETWEEN expression AND expression)
216        |
217        (NOT? IN LPAREN (expression ( COMMA expression)*)? RPAREN)
218    );
219
220columns: column (COMMA column)*;
221
222predicateGroup: LPAREN predicate ((AND|OR) predicate)* RPAREN;
223
224predicates: WHERE (predicate|predicateGroup) ((AND|OR) (predicate|predicateGroup))*;
225
226tables: FROM tableNames;
227
228/**
229 * The type of the literal value is
230 * checked afterwards on tree traversing
231 * otherwise there is conflict between token
232*/
233limit: LIMIT Number;
234
235orderBys: ORDER (RANDOM|BY orderByDef (COMMA orderByDef)*) ;
236
237orderByDef: SqlName (ASC | DESC)? ;
238
239/**
240* The main/root rule
241*/
242pageSql:
243        SELECT
244        RANDOM?
245        (STAR|columns)?
246        tables?
247        predicates?
248        orderBys?
249        limit?
250;
251