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// Tables
77PAGES:            P A G E S;
78BACKLINKS:        B A C K L I N K S;
79DESCENDANTS:       D E S C E N D A N T S;
80tableNames: PAGES | BACKLINKS | DESCENDANTS;
81
82// LITERALS
83fragment Letter : 'a'..'z' | 'A'..'Z';
84
85fragment HexDigit : 'a'..'f' | 'A'..'F';
86
87fragment Digit : '0'..'9' ;
88
89fragment Exponent : ('e' | 'E') ( PLUS|MINUS )? (Digit)+;
90
91fragment RegexComponent :
92    'a'..'z' | 'A'..'Z' | '0'..'9' | '_'
93    | PLUS | STAR | QUESTION | MINUS | DOT
94    | LPAREN | RPAREN | LSQUARE | RSQUARE | LCURLY | RCURLY
95    | BITWISEXOR | PIPE | DOLLAR | '!'
96    ;
97
98// https://www.sqlite.org/lang_expr.html
99// 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.
100StringLiteral :
101    ( '\'' ( ~'\'' | '\'\'')* '\''
102    | '"' ( ~('"') )* '"'
103    )+
104    ;
105
106CharSetLiteral
107    : StringLiteral
108    | '0' 'X' (HexDigit|Digit)+
109    ;
110
111IntegralLiteral
112    : (Digit)+ ('L' | 'S' | 'Y')
113    ;
114
115Number
116    : (Digit)+ ( DOT (Digit)* (Exponent)? | Exponent)?
117    ;
118
119NumberLiteral
120    : Number ('D' | 'B' 'D')
121    ;
122
123ByteLengthLiteral
124    : (Digit)+ ('b' | 'B' | 'k' | 'K' | 'm' | 'M' | 'g' | 'G')
125    ;
126
127
128/**
129 * Sql also does not permit
130 * to start with a number
131 * (just ot have no conflict with a NUMERIC_LITERAL)
132*/
133SqlName: (Letter | Digit) (Letter | Digit | '_')*;
134
135
136/**
137* Space are for human (discard)
138*/
139SPACES: [ \u000B\t\r\n] -> channel(HIDDEN);
140
141
142
143/**
144 * Fragment rules does not result in tokens visible to the parser.
145 * They aid in the recognition of tokens.
146*/
147
148fragment HEX_DIGIT: [0-9a-fA-F];
149fragment INTEGER_LITERAL: Digit+;
150fragment NUMERIC_LITERAL: Digit+ ('.' Digit*)?;
151fragment ALL_LITERAL_VALUE: StringLiteral | INTEGER_LITERAL | NUMERIC_LITERAL | NULL | TRUE
152   | FALSE
153   | NOW;
154
155
156fragment ANY_NAME: SqlName | StringLiteral | LPAREN ANY_NAME RPAREN;
157fragment A: [aA];
158fragment B: [bB];
159fragment C: [cC];
160fragment D: [dD];
161fragment E: [eE];
162fragment F: [fF];
163fragment G: [gG];
164fragment H: [hH];
165fragment I: [iI];
166fragment J: [jJ];
167fragment K: [kK];
168fragment L: [lL];
169fragment M: [mM];
170fragment N: [nN];
171fragment O: [oO];
172fragment P: [pP];
173fragment Q: [qQ];
174fragment R: [rR];
175fragment S: [sS];
176fragment T: [tT];
177fragment U: [uU];
178fragment V: [vV];
179fragment W: [wW];
180fragment X: [xX];
181fragment Y: [yY];
182fragment Z: [zZ];
183
184/**
185 * Parser (ie structure)
186 * https://github.com/antlr/antlr4/blob/master/doc/parser-rules.md
187*/
188
189sqlNames : SqlName|Number;
190
191column: sqlNames (DOT sqlNames)? (AS (sqlNames|StringLiteral))?;
192
193pattern: (StringLiteral|NumberLiteral);
194
195
196expression:
197    (SqlName|StringLiteral|NumberLiteral|Number)
198    | functionNames LPAREN expression? ( COMMA expression)* RPAREN
199;
200
201predicate: sqlNames
202    (
203        (( LESS_THAN | LESS_THAN_OR_EQUAL | GREATER_THAN | GREATER_THAN_OR_EQUAL | NOT_EQUAL | EQUAL) expression)
204        |
205        (
206            NOT?
207            (LIKE pattern (ESCAPE StringLiteral)?)
208            |
209            (GLOB pattern)
210        )
211        |
212        (NOT? BETWEEN expression AND expression)
213        |
214        (NOT? IN LPAREN (expression ( COMMA expression)*)? RPAREN)
215    );
216
217columns: column (COMMA column)*;
218
219predicateGroup: LPAREN predicate ((AND|OR) predicate)* RPAREN;
220
221predicates: WHERE (predicate|predicateGroup) ((AND|OR) (predicate|predicateGroup))*;
222
223tables: FROM tableNames;
224
225/**
226 * The type of the literal value is
227 * checked afterwards on tree traversing
228 * otherwise there is conflict between token
229*/
230limit: LIMIT Number;
231
232orderBys: ORDER (RANDOM|BY orderByDef (COMMA orderByDef)*) ;
233
234orderByDef: SqlName (ASC | DESC)? ;
235
236/**
237* The main/root rule
238*/
239pageSql:
240        SELECT
241        RANDOM?
242        (STAR|columns)?
243        tables?
244        predicates?
245        orderBys?
246        limit?
247;
248