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