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