Skip to content

Instantly share code, notes, and snippets.

@abyss7
Created September 29, 2020 14:27
Show Gist options
  • Save abyss7/5d51f7d40c8177bc3905451c2a65298c to your computer and use it in GitHub Desktop.
Save abyss7/5d51f7d40c8177bc3905451c2a65298c to your computer and use it in GitHub Desktop.
Buggy grammar
grammar test;
queryStmt: query (SEMICOLON | EOF) | insertStmt;
query
: alterStmt
| analyzeStmt
| createStmt
| optimizeStmt
| selectUnionStmt
| showStmt
;
// ALTER statement
alterStmt: ALTER TABLE tableIdentifier alterTableClause (COMMA alterTableClause)*;
alterTableClause: ADD COLUMN (IF NOT EXISTS)? tableColumnDfnt (AFTER nestedIdentifier)?;
// ANALYZE statement
analyzeStmt: ANALYZE queryStmt;
// CREATE statement
createStmt
: (ATTACH | CREATE) DATABASE (IF NOT EXISTS)? databaseIdentifier engineExpr?
| (ATTACH | CREATE) MATERIALIZED VIEW (IF NOT EXISTS)? tableIdentifier schemaClause? destinationClause? engineClause? POPULATE? subqueryClause
| (ATTACH | CREATE) TEMPORARY? TABLE (IF NOT EXISTS)? tableIdentifier schemaClause? engineClause? subqueryClause?
| (ATTACH | CREATE) VIEW (IF NOT EXISTS)? tableIdentifier subqueryClause
;
destinationClause: TO tableIdentifier;
subqueryClause: AS selectUnionStmt;
schemaClause: LPAREN tableElementExpr (COMMA tableElementExpr)* RPAREN;
engineClause:
engineExpr
( orderByClause
| partitionByClause
| primaryKeyClause
| sampleByClause
)*
;
partitionByClause: PARTITION BY columnExpr;
primaryKeyClause: PRIMARY KEY columnExpr;
sampleByClause: SAMPLE BY columnExpr;
engineExpr: ENGINE EQ_SINGLE? identifier (LPAREN columnExprList? RPAREN)?;
tableElementExpr: tableColumnDfnt;
tableColumnDfnt
: nestedIdentifier columnTypeExpr tableColumnPropertyExpr? (COMMENT STRING_LITERAL)? (TTL columnExpr)?
| nestedIdentifier columnTypeExpr? tableColumnPropertyExpr (COMMENT STRING_LITERAL)? (TTL columnExpr)?
;
tableColumnPropertyExpr: (DEFAULT | MATERIALIZED | ALIAS) columnExpr;
// INSERT statement
insertStmt: INSERT INTO TABLE? (tableIdentifier | FUNCTION tableFunctionExpr) columnsClause? dataClause;
columnsClause: LPAREN nestedIdentifier (COMMA nestedIdentifier)* RPAREN;
dataClause
: FORMAT identifier
| VALUES
| selectUnionStmt
;
// OPTIMIZE statement
optimizeStmt: OPTIMIZE TABLE tableIdentifier partitionClause? FINAL? DEDUPLICATE?;
partitionClause
: PARTITION columnExpr
| PARTITION ID STRING_LITERAL
;
// SELECT statement
selectUnionStmt: selectStmtWithParens (UNION ALL selectStmtWithParens)*;
selectStmtWithParens: selectStmt | LPAREN selectUnionStmt RPAREN;
selectStmt:
withClause?
SELECT DISTINCT? columnExprList
fromClause?
arrayJoinClause?
prewhereClause?
whereClause?
groupByClause?
havingClause?
orderByClause?
;
withClause: WITH columnExprList;
fromClause: FROM joinExpr FINAL?;
arrayJoinClause: LEFT? ARRAY JOIN columnExprList;
prewhereClause: PREWHERE columnExpr;
whereClause: WHERE columnExpr;
groupByClause: GROUP BY columnExprList (WITH TOTALS)?;
havingClause: HAVING columnExpr;
orderByClause: ORDER BY orderExprList;
joinExpr
: LPAREN joinExpr RPAREN
| joinExpr (GLOBAL|LOCAL)? joinOp? JOIN joinExpr joinConstraintClause
| joinExpr joinOpCross joinExpr
| tableExpr
;
joinOp
: (ANY? INNER | INNER ANY?)
| ((OUTER | SEMI | ANTI | ANY | ASOF)? (LEFT | RIGHT) | (LEFT | RIGHT) (OUTER | SEMI | ANTI | ANY | ASOF)?)
| ((OUTER | ANY)? FULL | FULL (OUTER | ANY)?)
;
joinOpCross
: (GLOBAL|LOCAL)? CROSS JOIN
| COMMA
;
joinConstraintClause
: ON columnExprList
| USING LPAREN columnExprList RPAREN
| USING columnExprList
;
orderExprList: orderExpr (COMMA orderExpr)*;
orderExpr: columnExpr (ASCENDING | DESCENDING | DESC)? (NULLS (FIRST | LAST))? (COLLATE STRING_LITERAL)?;
// SHOW statements
showStmt
: SHOW CREATE DATABASE databaseIdentifier
| SHOW CREATE TEMPORARY? TABLE? tableIdentifier
| SHOW TEMPORARY? TABLES ((FROM | IN) databaseIdentifier)? (LIKE STRING_LITERAL | whereClause)?
| SHOW DATABASES
;
// Columns
columnTypeExpr
: identifier
| identifier LPAREN columnExprList RPAREN
| identifier LPAREN columnTypeExpr (COMMA columnTypeExpr)* RPAREN
| identifier LPAREN identifier columnTypeExpr (COMMA identifier columnTypeExpr)* RPAREN
;
columnExprList: columnExpr (COMMA columnExpr)*;
columnExpr
: CAST LPAREN columnExpr AS identifier RPAREN
| identifier (LPAREN columnExprList? RPAREN)? LPAREN columnExprList? RPAREN
| columnExpr AS? identifier
| columnIdentifier
| literal
;
columnIdentifier: (tableIdentifier DOT)? nestedIdentifier;
nestedIdentifier: identifier (DOT identifier)?;
// Tables
tableExpr
: tableIdentifier
| tableFunctionExpr
| LPAREN selectUnionStmt RPAREN
| tableExpr AS? identifier
;
tableFunctionExpr: identifier LPAREN tableArgList? RPAREN;
tableIdentifier: (databaseIdentifier DOT)? identifier;
tableArgList: tableArgExpr (COMMA tableArgExpr)*;
tableArgExpr
: tableExpr
| literal
;
// Databases
databaseIdentifier: identifier;
// Basics
literal: STRING_LITERAL;
identifier: IDENTIFIER;
// Keywords
ADD: A D D;
AFTER: A F T E R;
ALIAS: A L I A S;
ALL: A L L;
ALTER: A L T E R;
ANALYZE: A N A L Y Z E;
ANTI: A N T I;
ANY: A N Y;
ARRAY: A R R A Y;
AS: A S;
ASCENDING: A S C | A S C E N D I N G;
ASOF: A S O F;
ATTACH: A T T A C H;
BY: B Y;
CAST: C A S T;
CLEAR: C L E A R;
COLLATE: C O L L A T E;
COLUMN: C O L U M N;
COMMENT: C O M M E N T;
CREATE: C R E A T E;
CROSS: C R O S S;
DATABASE: D A T A B A S E;
DATABASES: D A T A B A S E S;
DEDUPLICATE: D E D U P L I C A T E;
DEFAULT: D E F A U L T;
DELETE: D E L E T E;
DESC: D E S C;
DESCENDING: D E S C E N D I N G;
DETACH: D E T A C H;
DISK: D I S K;
DISTINCT: D I S T I N C T;
DROP: D R O P;
ENGINE: E N G I N E;
EXISTS: E X I S T S;
FINAL: F I N A L;
FIRST: F I R S T;
FORMAT: F O R M A T;
FROM: F R O M;
FULL: F U L L;
FUNCTION: F U N C T I O N;
GLOBAL: G L O B A L;
GROUP: G R O U P;
HAVING: H A V I N G;
ID: I D;
IF: I F;
IN: I N;
INNER: I N N E R;
INSERT: I N S E R T;
INTO: I N T O;
JOIN: J O I N;
KEY: K E Y;
LAST: L A S T;
LEFT: L E F T;
LIKE: L I K E;
LIMIT: L I M I T;
LOCAL: L O C A L;
MATERIALIZED: M A T E R I A L I Z E D;
MODIFY: M O D I F Y;
NOT: N O T;
NULLS: N U L L S;
ON: O N;
OPTIMIZE: O P T I M I Z E;
ORDER: O R D E R;
OUTER: O U T E R;
PARTITION: P A R T I T I O N;
POPULATE: P O P U L A T E;
PREWHERE: P R E W H E R E;
PRIMARY: P R I M A R Y;
RIGHT: R I G H T;
SAMPLE: S A M P L E;
SELECT: S E L E C T;
SEMI: S E M I;
SHOW: S H O W;
TABLE: T A B L E;
TABLES: T A B L E S;
TEMPORARY: T E M P O R A R Y;
TO: T O;
TOTALS: T O T A L S;
TTL: T T L;
UNION: U N I O N;
USING: U S I N G;
VALUES: V A L U E S;
VIEW: V I E W;
WHERE: W H E R E;
WITH: W I T H;
// Tokens
IDENTIFIER: LETTER+;
// It's important that quote-symbol is a single character.
STRING_LITERAL: QUOTE_SINGLE ( ~([\\']) | (BACKSLASH .) | (QUOTE_SINGLE QUOTE_SINGLE) )* QUOTE_SINGLE;
// Alphabet and allowed symbols
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];
fragment LETTER: [a-zA-Z];
BACKSLASH: '\\';
COMMA: ',';
DOT: '.';
EQ_SINGLE: '=';
LPAREN: '(';
QUOTE_SINGLE: '\'';
RPAREN: ')';
SEMICOLON: ';';
WHITESPACE: [ \u000B\u000C\t\r\n] -> skip; // '\n' can be part of multiline single query
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment