andand = "&&" .
andnot = "&^" .
ascii_letter = "a" … "z" | "A" … "Z" .
big_u_value = "\\" "U" hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit .
byte_value = octal_byte_value | hex_byte_value .
decimal_digit = "0" … "9" .
decimal_lit = ( "1" … "9" ) { decimal_digit } .
decimals = decimal_digit { decimal_digit } .
eq = "==" | "=" .
escaped_char = "\\" (
		  "a"
		| "b"
		| "f"
		| "n"
		| "r"
		| "t"
		| "v"
		| "\\"
		| "'"
		| "\""
	  ) .
exponent = ( "e" | "E" ) [ "+" | "-" ] decimals .
float_lit = decimals "." [ decimals ] [ exponent ]
	| decimals exponent
	| "." decimals [ exponent ] .
ge = ">=" .
hex_byte_value = "\\" "x" hex_digit hex_digit .
hex_digit = "0" … "9"
	| "A" … "F"
	| "a" … "f" .
hex_lit = "0" ( "x" | "X" ) hex_digit { hex_digit } .
identifier = letter { letter | decimal_digit } .
imaginary_lit = ( decimals | float_lit ) "i" .
int_lit = decimal_lit
	| octal_lit
	| hex_lit .
interpreted_string_lit = "\"" { unicode_value | byte_value } "\"" .
le = "<=" .
letter = ascii_letter | "_" .
little_u_value = "\\" "u" hex_digit hex_digit hex_digit hex_digit .
lsh = "<<" .
neq = "!=" .
newline = .
octal_byte_value = "\\" octal_digit octal_digit octal_digit .
octal_digit = "0" … "7" .
octal_lit = "0" { octal_digit } .
oror = "||" .
ql_parameter = ( "?" | "$" ) "1" … "9" { "0" … "9" } .
raw_string_lit = "`" { unicode_char | newline } "`" .
rsh = ">>" .
rune_lit = "'" ( unicode_value | byte_value ) "'" .
string_lit = raw_string_lit | interpreted_string_lit .
unicode_char = .
unicode_value = unicode_char
	| little_u_value
	| big_u_value
	| escaped_char .

AlterTableStmt = "ALTER" "TABLE" TableName (
		  "ADD" ColumnDef
		| "DROP" "COLUMN" ColumnName
	  ) .
Assignment = ColumnName "=" Expression .
AssignmentList = Assignment { "," Assignment } [ "," ] .
BeginTransactionStmt = "BEGIN" "TRANSACTION" .
Call = "(" [ "*" | ExpressionList ] ")" .
ColumnDef = ColumnName Type [
		  "NOT" "NULL"
		| Expression
	  ] [ "DEFAULT" Expression ] .
ColumnName = identifier .
ColumnNameList = ColumnName { "," ColumnName } [ "," ] .
CommitStmt = "COMMIT" .
Conversion = Type "(" Expression ")" .
CreateIndexStmt = "CREATE" [ "UNIQUE" ] "INDEX" [
		 "IF" "NOT" "EXISTS"
	  ] IndexName "ON" TableName "(" ExpressionList ")" .
CreateTableStmt = "CREATE" "TABLE" [
		 "IF" "NOT" "EXISTS"
	  ] TableName "(" ColumnDef { "," ColumnDef } [ "," ] ")" .
DeleteFromStmt = "DELETE" "FROM" TableName [ WhereClause ] .
DropIndexStmt = "DROP" "INDEX" [ "IF" "EXISTS" ] IndexName .
DropTableStmt = "DROP" "TABLE" [ "IF" "EXISTS" ] TableName .
EmptyStmt = .
ExplainStmt = "EXPLAIN" Statement .
Expression = Term {
		 ( oror | "OR" ) Term
	  } .
ExpressionList = Expression { "," Expression } [ "," ] .
Factor = PrimaryFactor {
		 (
			  ge
			| ">"
			| le
			| "<"
			| neq
			| eq
			| "LIKE"
		  ) PrimaryFactor
	  } [ Predicate ] .
Field = Expression [ "AS" identifier ] .
FieldList = Field { "," Field } [ "," ] .
GroupByClause = "GROUP BY" ColumnNameList .
Index = "[" Expression "]" .
IndexName = identifier .
InsertIntoStmt = "INSERT" "INTO" TableName [
		 "(" ColumnNameList ")"
	  ] ( Values | SelectStmt ) .
JoinClause = (
		  "LEFT"
		| "RIGHT"
		| "FULL"
	  ) [ "OUTER" ] "JOIN" RecordSet "ON" Expression .
Limit = "Limit" Expression .
Literal = "FALSE"
	| "NULL"
	| "TRUE"
	| float_lit
	| imaginary_lit
	| int_lit
	| rune_lit
	| string_lit
	| ql_parameter .
Offset = "OFFSET" Expression .
Operand = Literal
	| QualifiedIdent
	| "(" Expression ")" .
OrderBy = "ORDER" "BY" ExpressionList [ "ASC" | "DESC" ] .
Predicate = (
		  [ "NOT" ] (
			  "IN" "(" ExpressionList ")"
			| "IN" "(" SelectStmt [ ";" ] ")"
			| "BETWEEN" PrimaryFactor "AND" PrimaryFactor
		  )
		| "IS" [ "NOT" ] "NULL"
	  ) .
PrimaryExpression = Operand
	| Conversion
	| PrimaryExpression Index
	| PrimaryExpression Slice
	| PrimaryExpression Call .
PrimaryFactor = PrimaryTerm {
		 (
			  "^"
			| "|"
			| "-"
			| "+"
		  ) PrimaryTerm
	  } .
PrimaryTerm = UnaryExpr {
		 (
			  andnot
			| "&"
			| lsh
			| rsh
			| "%"
			| "/"
			| "*"
		  ) UnaryExpr
	  } .
QualifiedIdent = identifier [ "." identifier ] .
RecordSet = (
		  TableName
		| "(" SelectStmt [ ";" ] ")"
	  ) [ "AS" identifier ] .
RecordSetList = RecordSet { "," RecordSet } [ "," ] .
RollbackStmt = "ROLLBACK" .
SelectStmt = "SELECT" [ "DISTINCT" ] ( "*" | FieldList ) "FROM" RecordSetList [ JoinClause ] [ WhereClause ] [ GroupByClause ] [ OrderBy ] [ Limit ] [ Offset ] .
Slice = "[" [ Expression ] ":" [ Expression ] "]" .
Statement = EmptyStmt
	| AlterTableStmt
	| BeginTransactionStmt
	| CommitStmt
	| CreateIndexStmt
	| CreateTableStmt
	| DeleteFromStmt
	| DropIndexStmt
	| DropTableStmt
	| InsertIntoStmt
	| RollbackStmt
	| SelectStmt
	| TruncateTableStmt
	| UpdateStmt
	| ExplainStmt .
StatementList = Statement { ";" Statement } .
TableName = identifier .
Term = Factor {
		 ( andand | "AND" ) Factor
	  } .
TruncateTableStmt = "TRUNCATE" "TABLE" TableName .
Type = "bigint"
	| "bigrat"
	| "blob"
	| "bool"
	| "byte"
	| "complex128"
	| "complex64"
	| "duration"
	| "float"
	| "float32"
	| "float64"
	| "int"
	| "int16"
	| "int32"
	| "int64"
	| "int8"
	| "rune"
	| "string"
	| "time"
	| "uint"
	| "uint16"
	| "uint32"
	| "uint64"
	| "uint8" .
UnaryExpr = [
		  "^"
		| "!"
		| "-"
		| "+"
	  ] PrimaryExpression .
UpdateStmt = "UPDATE" TableName [ "SET" ] AssignmentList [ WhereClause ] .
Values = "VALUES" "(" ExpressionList ")" {
		 "," "(" ExpressionList ")"
	  } [ "," ] .
WhereClause = "WHERE" Expression .
