Files
sqlitebrowser/src/grammar/sqlite3.g
Martin Kleusberg 2dd0e9516f Grammar: Allow multiple table keys which are not separated by commas
Fix table definitions like this...
CREATE TABLE [player_tech_branches]
(
	[from_id] INTEGER NOT NULL REFERENCES [techs](id),
	[to_id] INTEGER NOT NULL REFERENCES [techs](id),

	UNIQUE ([from_id], [to_id]) PRIMARY KEY ([from_id], [to_id])
)
...where there are multiple keys which are not separated by commas.

This partially fixed EoD's database in issue #63.
2014-07-26 21:41:12 +02:00

478 lines
7.8 KiB
Plaintext

options {
language="Cpp";
genHashLines=false;
}
class Sqlite3Lexer extends Lexer;
options {
k=2;
exportVocab=sqlite3;
caseSensitive=false;
caseSensitiveLiterals=false;
charVocabulary='\u0000'..'\uFFFE';
}
tokens {
ABORT="ABORT";
ACTION="ACTION";
AUTOINCREMENT="AUTOINCREMENT";
AS="AS";
ASC="ASC";
AND="AND";
OR="OR";
BETWEEN="BETWEEN";
CASCADE="CASCADE";
CASE_T="CASE";
CAST="CAST";
CHECK="CHECK";
CREATE="CREATE";
COLLATE="COLLATE";
CONFLICT="CONFLICT";
CONSTRAINT="CONSTRAINT";
CURRENT_TIME="CURRENT_TIME";
CURRENT_DATE="CURRENT_DATE";
CURRENT_TIMESTAMP="CURRENT_TIMESTAMP";
DEFAULT="DEFAULT";
DEFERRABLE="DEFERRABLE";
DEFERRED="DEFERRED";
DELETE="DELETE";
DESC="DESC";
ELSE_T="ELSE";
END="END";
ESCAPE="ESCAPE";
FAIL="FAIL";
FOREIGN="FOREIGN";
GLOB="GLOB";
KEY="KEY";
LIKE="LIKE";
TABLE="TABLE";
IF_T="IF";
IGNORE="IGNORE";
IN="IN";
INITIALLY="INITIALLY";
INSERT="INSERT";
IMMEDIATE="IMMEDIATE";
IS="IS";
NO="NO";
NOT="NOT";
NULL_T="NULL";
MATCH="MATCH";
EXISTS="EXISTS";
ON="ON";
PRIMARY="PRIMARY";
RAISE="RAISE";
REFERENCES="REFERENCES";
REGEXP="REGEXP";
REPLACE="REPLACE";
RESTRICT="RESTRICT";
ROLLBACK="ROLLBACK";
ROWID="ROWID";
SET="SET";
TEMPORARY="TEMPORARY";
TEMP="TEMP";
THEN="THEN";
UNIQUE="UNIQUE";
UPDATE="UPDATE";
WHEN="WHEN";
WITHOUT="WITHOUT";
//ast
TYPE_NAME;
COLUMNDEF;
COLUMNCONSTRAINT;
TABLECONSTRAINT;
CREATETABLE;
KEYWORDASTABLENAME;
KEYWORDASCOLUMNNAME;
}
protected
DIGIT : '0'..'9' ;
protected DOT:;
ID
:
// 00C0 - 02B8 load of good looking unicode chars
// there might be more allowed characters
('a'..'z'|'_') ('a'..'z'|'0'..'9'|'_'|'\u0080'..'\u02B8')*
;
QUOTEDID
: '`' ( ~('`') )* '`'
| '[' ( ~(']') )* ']'
;
QUOTEDLITERAL
: '"' ( ~('"') )* '"'
;
NUMERIC
: ( (DIGIT)+ ( '.' (DIGIT)* )?
| '.' { _ttype=DOT; } (DIGIT)+)
( 'e' (PLUS|MINUS)? (DIGIT)+ )?
;
protected
NL :
( '\r'
| '\n' {newline();}
);
COMMENT :
( '-''-' (~('\n'|'\r'))* NL {newline();} // single line comment
| '/''*' ( options{greedy=false;} : NL {newline();} | ~('\n'|'\r') )* '*''/' // multi-line comment
) { $setType(ANTLR_USE_NAMESPACE(antlr)Token::SKIP); };
WS :
( ' '
| '\t'
| '\f'
| NL
) { $setType(ANTLR_USE_NAMESPACE(antlr)Token::SKIP); };
STRINGLITERAL
:
// '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
'\'' ( ~('\'') )* '\''
;
//protected
//ESC_SEQ
// : '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
// ;
LPAREN : '(';
RPAREN : ')';
COMMA : ',';
SEMI : ';';
PLUS : '+';
MINUS : '-';
STAR : '*';
TILDE : '~';
AMPERSAND: '&';
BITOR: '|';
OROP: BITOR BITOR;
EQUAL: '=';
EQUAL2: EQUAL EQUAL;
GREATER: '>';
GREATEREQUAL: GREATER EQUAL;
LOWER: '<';
LOWEREQUAL: LOWER EQUAL;
UNEQUAL: '!' EQUAL;
UNEQUAL2: LOWER GREATER;
BITWISELEFT: LOWER LOWER;
BITWISERIGHT: GREATER GREATER;
// parser
class Sqlite3Parser extends Parser;
options {
k=2;
buildAST = true;
}
id : ID | QUOTEDID | QUOTEDLITERAL | STRINGLITERAL ;
databasename
:
id
;
tablename
:
id
;
columnname
:
id
;
identifier
:
((databasename)? DOT)? tablename
;
collationname
:
ID
;
signednumber
: (PLUS | MINUS)? NUMERIC
// {#signednumber = #([SIGNEDNUMBER, "SIGNEDNUMBER"], #signednumber);}
;
// parser part
statementlist
:
(statement)?
(SEMI statement)*
;
statement
:
createtable
;
create_statements
:
createtable
;
keywordastablename
:
( ABORT
| ACTION
| ASC
| CASCADE
| CAST
| CONFLICT
| CURRENT_TIME
| CURRENT_DATE
| CURRENT_TIMESTAMP
| DEFERRED
| DESC
| END
| FAIL
| GLOB
| KEY
| LIKE
| IGNORE
| INITIALLY
| IMMEDIATE
| MATCH
| RAISE
| REGEXP
| REPLACE
| RESTRICT
| ROLLBACK
| TEMPORARY
| TEMP
)
{#keywordastablename = #([KEYWORDASTABLENAME, "KEYWORDASTABLENAME"], #keywordastablename);}
;
createtable
:
CREATE (TEMP|TEMPORARY)? TABLE (IF_T NOT EXISTS)? (tablename | keywordastablename)
( LPAREN columndef (COMMA columndef)* ((COMMA)? tableconstraint)* RPAREN (WITHOUT ROWID)?
| AS selectstmt
)
{#createtable = #([CREATETABLE, "CREATETABLE"], #createtable);}
;
keywordascolumnname
:
( ABORT
| ACTION
| AUTOINCREMENT
| AS
| ASC
| AND
| OR
| CASCADE
| CASE_T
| CAST
| CREATE
| COLLATE
| CONFLICT
| CURRENT_TIME
| CURRENT_DATE
| CURRENT_TIMESTAMP
| DEFAULT
| DEFERRABLE
| DEFERRED
| DELETE
| DESC
| ELSE_T
| END
| ESCAPE
| FAIL
| GLOB
| KEY
| LIKE
| TABLE
| IF_T
| IGNORE
| INITIALLY
| IMMEDIATE
| IS
| NOT
| NULL_T
| MATCH
| EXISTS
| ON
| RAISE
| REFERENCES
| REGEXP
| REPLACE
| RESTRICT
| ROLLBACK
| SET
| TEMPORARY
| TEMP
| THEN
| UPDATE
| WHEN
)
{#keywordascolumnname = #([KEYWORDASCOLUMNNAME, "KEYWORDASCOLUMNNAME"], #keywordascolumnname);}
;
columndef
:
(columnname | keywordascolumnname) (type_name)? (columnconstraint)*
{#columndef = #([COLUMNDEF, "COLUMNDEF"], #columndef);}
;
name : ID | QUOTEDID | QUOTEDLITERAL | STRINGLITERAL;
type_name
:
(name)+
(LPAREN signednumber (COMMA signednumber)? RPAREN)?
{#type_name = #([TYPE_NAME, "TYPE_NAME"], #type_name);}
;
columnconstraint
:
(CONSTRAINT name)?
( PRIMARY KEY (ASC|DESC)? (AUTOINCREMENT)?
| (NOT)? NULL_T (conflictclause)?
| UNIQUE (conflictclause)?
| CHECK LPAREN expr RPAREN
| DEFAULT (signednumber | QUOTEDLITERAL | STRINGLITERAL | LPAREN expr RPAREN | literalvalue)
| COLLATE collationname
| foreignkeyclause)
{#columnconstraint = #([COLUMNCONSTRAINT, "COLUMNCONSTRAINT"], #columnconstraint);}
;
tableconstraint
:
(CONSTRAINT name)?
( PRIMARY KEY LPAREN indexedcolumn (COMMA indexedcolumn)* RPAREN (conflictclause)?
| UNIQUE LPAREN indexedcolumn (COMMA indexedcolumn)* RPAREN (conflictclause)?
| CHECK LPAREN expr RPAREN
| FOREIGN KEY LPAREN columnname (COMMA columnname)* RPAREN foreignkeyclause
)
{#tableconstraint = #([TABLECONSTRAINT, "TABLECONSTRAINT"], #tableconstraint);}
;
indexedcolumn
: id
;
conflictclause
:
ON CONFLICT
( ROLLBACK
| ABORT
| FAIL
| IGNORE
| REPLACE
)
;
foreignkeyclause
:
REFERENCES tablename (LPAREN columnname (COMMA columnname)* RPAREN)?
( ON (DELETE | UPDATE | INSERT)
( SET (NULL_T | DEFAULT)
| CASCADE
| RESTRICT
| NO ACTION
)
| MATCH name
)*
( (NOT DEFERRABLE) => NOT DEFERRABLE (INITIALLY (DEFERRED | IMMEDIATE))?
| DEFERRABLE (INITIALLY (DEFERRED | IMMEDIATE) ) )?
;
selectstmt
: SELECT
;
functionname
: id ;
expr
:
subexpr ((binaryoperator | AND | OR) subexpr )*
;
subexpr
:
( MINUS | PLUS | TILDE | NOT)?
( literalvalue
// | bindparameter TODO
| ((databasename DOT)? tablename)? columnname
| functionname LPAREN (expr (COMMA expr)* )? RPAREN //TODO
| castexpr
| (EXISTS)? LPAREN (expr | selectstmt) RPAREN
| caseexpr
| raisefunction
)
(suffixexpr)?
;
castexpr
:
CAST LPAREN expr AS type_name RPAREN
;
caseexpr
:
CASE_T (expr)? (WHEN expr THEN expr)+ (ELSE_T expr)? END
;
like_operator
:
LIKE
| GLOB
| REGEXP
| MATCH
;
between_subexpr
:
subexpr (AND subexpr)+
;
suffixexpr
:
COLLATE collationname
| (NOT)?
( BETWEEN subexpr ((binaryoperator | OR) subexpr )* AND expr
| IN ( LPAREN (selectstmt | expr (COMMA expr)* )? RPAREN | tablename)
| like_operator subexpr (ESCAPE subexpr)?
)
;
literalvalue
:
NUMERIC
// | STRINGLITERAL // captured by columnname
// | blob-literal
| NULL_T
| CURRENT_TIME
| CURRENT_DATE
| CURRENT_TIMESTAMP
;
raisefunction
: RAISE LPAREN ( IGNORE | (ROLLBACK | ABORT | FAIL) COMMA STRINGLITERAL ) RPAREN ;
binaryoperator
:
OROP
| STAR | SLASH | PERCENT
| PLUS | MINUS
| BITWISELEFT | BITWISERIGHT | AMPERSAND | BITOR
| LOWER | LOWEREQUAL | GREATER | GREATEREQUAL
| EQUAL | EQUAL2 | UNEQUAL | UNEQUAL2
| IS | like_operator
;