hyrise/sql-parser

Grammar railroad diagram

mingodad opened this issue · 0 comments

Using this tool https://www.bottlecaps.de/convert/ and manually adding the tokens from src/parser/flex_lexer.l we can see a railroad diagram for the grammar in src/parser/bison_parser.y copy and paste the EBNF shown bellow on https://www.bottlecaps.de/rr/ui in the tab Edit Grammar then switching to the tab View Diagram.

/*
From https://raw.githubusercontent.com/hyrise/sql-parser/master/src/parser/bison_parser.y
*/

/* converted on Sun Jul 18, 2021, 10:06 (UTC+02) by bison-to-w3c v0.53 which is Copyright (c) 2011-2021 by Gunther Rademacher <grd@gmx.net> */

input    ::= statement ( ';' statement )* opt_semicolon
statement
         ::= ( prepare_statement | preparable_statement ) opt_hints
           | show_statement
           | import_statement
           | export_statement
preparable_statement
         ::= select_statement
           | create_statement
           | insert_statement
           | delete_statement
           | truncate_statement
           | update_statement
           | drop_statement
           | execute_statement
           | transaction_statement
opt_hints
         ::= ( WITH HINT '(' hint ( ',' hint )* ')' )?
hint     ::= IDENTIFIER ( '(' literal_list ')' )?
transaction_statement
         ::= ( BEGIN | ROLLBACK | COMMIT ) opt_transaction_keyword
opt_transaction_keyword
         ::= TRANSACTION?
prepare_statement
         ::= PREPARE IDENTIFIER FROM prepare_target_query
prepare_target_query
         ::= STRING
execute_statement
         ::= EXECUTE IDENTIFIER ( '(' opt_literal_list ')' )?
import_statement
         ::= IMPORT FROM file_type FILE file_path INTO table_name
           | COPY table_name FROM file_path opt_file_type
file_type
         ::= IDENTIFIER
file_path
         ::= string_literal
opt_file_type
         ::= ( WITH FORMAT file_type )?
export_statement
         ::= COPY table_name TO file_path opt_file_type
show_statement
         ::= SHOW ( TABLES | COLUMNS table_name )
           | DESCRIBE table_name
create_statement
         ::= CREATE ( TABLE opt_not_exists table_name ( FROM IDENTIFIER FILE file_path | '(' column_def ( ',' column_def )* ')' | AS select_statement ) | VIEW opt_not_exists table_name opt_column_list AS select_statement )
opt_not_exists
         ::= ( IF NOT EXISTS )?
column_def
         ::= IDENTIFIER column_type opt_column_nullable
column_type
         ::= INT
           | INTEGER
           | LONG
           | FLOAT
           | DOUBLE
           | ( VARCHAR | CHAR ) '(' INTVAL ')'
           | TEXT
           | DATETIME
           | DATE
opt_column_nullable
         ::= ( NOT? NULL )?
drop_statement
         ::= DROP ( TABLE | VIEW ) opt_exists table_name
           | DEALLOCATE PREPARE IDENTIFIER
opt_exists
         ::= ( IF EXISTS )?
delete_statement
         ::= DELETE FROM table_name opt_where
truncate_statement
         ::= TRUNCATE table_name
insert_statement
         ::= INSERT INTO table_name opt_column_list ( VALUES '(' literal_list ')' | select_no_paren )
opt_column_list
         ::= ( '(' ident_commalist ')' )?
update_statement
         ::= UPDATE table_ref_name_no_alias SET update_clause ( ',' update_clause )* opt_where
update_clause
         ::= IDENTIFIER '=' expr
select_statement
         ::= opt_with_clause ( select_with_paren ( set_operator select_within_set_operation opt_order opt_limit )? | select_no_paren )
select_within_set_operation
         ::= select_with_paren
           | select_within_set_operation_no_parentheses
select_within_set_operation_no_parentheses
         ::= select_clause ( set_operator select_within_set_operation )?
select_with_paren
         ::= '(' ( select_no_paren | select_with_paren ) ')'
select_no_paren
         ::= select_clause ( set_operator select_within_set_operation )? opt_order opt_limit
set_operator
         ::= set_type opt_all
set_type ::= UNION
           | INTERSECT
           | EXCEPT
opt_all  ::= ALL?
select_clause
         ::= SELECT opt_top opt_distinct select_list opt_from_clause opt_where opt_group
opt_distinct
         ::= DISTINCT?
select_list
         ::= expr_list
opt_from_clause
         ::= from_clause?
from_clause
         ::= FROM table_ref
opt_where
         ::= ( WHERE expr )?
opt_group
         ::= ( GROUP BY expr_list opt_having )?
opt_having
         ::= ( HAVING expr )?
opt_order
         ::= ( ORDER BY order_desc ( ',' order_desc )* )?
order_desc
         ::= expr opt_order_type
opt_order_type
         ::= ( ASC | DESC )?
opt_top  ::= ( TOP int_literal )?
opt_limit
         ::= ( LIMIT ( expr | ALL ) )? ( OFFSET expr )?
expr_list
         ::= expr_alias ( ',' expr_alias )*
opt_literal_list
         ::= literal_list?
literal_list
         ::= literal ( ',' literal )*
expr_alias
         ::= expr opt_alias
expr     ::= operand
           | between_expr
           | logic_expr
           | exists_expr
           | in_expr
operand  ::= '(' ( expr | select_no_paren ) ')'
           | array_index
           | scalar_expr
           | unary_expr
           | binary_expr
           | case_expr
           | function_expr
           | extract_expr
           | cast_expr
           | array_expr
scalar_expr
         ::= column_name
           | literal
unary_expr
         ::= ( '-' | NOT ) operand
           | operand ( ISNULL | IS NOT? NULL )
binary_expr
         ::= comp_expr
           | operand ( '-' | '+' | '/' | '*' | '%' | '^' | NOT? LIKE | ILIKE | CONCAT ) operand
logic_expr
         ::= expr ( AND | OR ) expr
in_expr  ::= operand NOT? IN '(' ( expr_list | select_no_paren ) ')'
case_expr
         ::= CASE expr? case_list ( ELSE expr )? END
case_list
         ::= ( WHEN expr THEN expr )+
exists_expr
         ::= NOT? EXISTS '(' select_no_paren ')'
comp_expr
         ::= operand ( '=' | EQUALS | NOTEQUALS | '<' | '>' | LESSEQ | GREATEREQ ) operand
function_expr
         ::= IDENTIFIER '(' ( opt_distinct expr_list )? ')'
extract_expr
         ::= EXTRACT '(' datetime_field FROM expr ')'
cast_expr
         ::= CAST '(' expr AS column_type ')'
datetime_field
         ::= SECOND
           | MINUTE
           | HOUR
           | DAY
           | MONTH
           | YEAR
array_expr
         ::= ARRAY '[' expr_list ']'
array_index
         ::= operand '[' int_literal ']'
between_expr
         ::= operand BETWEEN operand AND operand
column_name
         ::= IDENTIFIER ( '.' ( IDENTIFIER | '*' ) )?
           | '*'
literal  ::= string_literal
           | bool_literal
           | num_literal
           | null_literal
           | date_literal
           | '?'
string_literal
         ::= STRING
bool_literal
         ::= TRUE
           | FALSE
num_literal
         ::= FLOATVAL
           | int_literal
int_literal
         ::= INTVAL
null_literal
         ::= NULL
date_literal
         ::= DATE STRING
table_ref
         ::= table_ref_atomic ( ',' table_ref_atomic )*
table_ref_atomic
         ::= nonjoin_table_ref_atomic
           | join_clause
nonjoin_table_ref_atomic
         ::= table_ref_name
           | '(' select_statement ')' opt_table_alias
table_ref_name
         ::= table_name opt_table_alias
table_ref_name_no_alias
         ::= table_name
table_name
         ::= IDENTIFIER ( '.' IDENTIFIER )?
table_alias
         ::= alias
           | AS IDENTIFIER '(' ident_commalist ')'
opt_table_alias
         ::= table_alias?
alias    ::= AS? IDENTIFIER
opt_alias
         ::= alias?
opt_with_clause
         ::= with_clause?
with_clause
         ::= WITH with_description ( ',' with_description )*
with_description
         ::= IDENTIFIER AS select_with_paren
join_clause
         ::= table_ref_atomic ( NATURAL JOIN nonjoin_table_ref_atomic | opt_join_type JOIN table_ref_atomic ( ON join_condition | USING '(' column_name ')' ) )
opt_join_type
         ::= ( LEFT | RIGHT | FULL )? OUTER?
           | INNER
           | CROSS
join_condition
         ::= expr
opt_semicolon
         ::= ';'?
ident_commalist
         ::= IDENTIFIER ( ',' IDENTIFIER )*

// Tokens from https://github.com/hyrise/sql-parser/blob/master/src/parser/flex_lexer.l

DEALLOCATE ::= "DEALLOCATE"
PARAMETERS ::= "PARAMETERS"
INTERSECT ::= "INTERSECT"
TEMPORARY ::= "TEMPORARY"
TIMESTAMP ::= "TIMESTAMP"
DESCRIBE ::= "DESCRIBE"
DISTINCT ::= "DISTINCT"
NVARCHAR ::= "NVARCHAR"
RESTRICT ::= "RESTRICT"
TRUNCATE ::= "TRUNCATE"
ANALYZE ::= "ANALYZE"
BETWEEN ::= "BETWEEN"
CASCADE ::= "CASCADE"
COLUMNS ::= "COLUMNS"
CONTROL ::= "CONTROL"
DEFAULT ::= "DEFAULT"
EXECUTE ::= "EXECUTE"
EXPLAIN ::= "EXPLAIN"
INTEGER ::= "INTEGER"
NATURAL ::= "NATURAL"
PREPARE ::= "PREPARE"
PRIMARY ::= "PRIMARY"
SCHEMAS ::= "SCHEMAS"
SPATIAL ::= "SPATIAL"
VARCHAR ::= "VARCHAR"
VIRTUAL ::= "VIRTUAL"
BEFORE ::= "BEFORE"
COLUMN ::= "COLUMN"
CREATE ::= "CREATE"
DELETE ::= "DELETE"
DIRECT ::= "DIRECT"
DOUBLE ::= "DOUBLE"
ESCAPE ::= "ESCAPE"
EXCEPT ::= "EXCEPT"
EXISTS ::= "EXISTS"
EXTRACT ::= "EXTRACT"
CAST ::= "CAST"
FORMAT ::= "FORMAT"
GLOBAL ::= "GLOBAL"
HAVING ::= "HAVING"
IMPORT ::= "IMPORT"
INSERT ::= "INSERT"
ISNULL ::= "ISNULL"
OFFSET ::= "OFFSET"
RENAME ::= "RENAME"
SCHEMA ::= "SCHEMA"
SELECT ::= "SELECT"
SORTED ::= "SORTED"
TABLES ::= "TABLES"
UNIQUE ::= "UNIQUE"
UNLOAD ::= "UNLOAD"
UPDATE ::= "UPDATE"
VALUES ::= "VALUES"
AFTER ::= "AFTER"
ALTER ::= "ALTER"
ARRAY ::= "ARRAY"
CROSS ::= "CROSS"
DELTA ::= "DELTA"
FLOAT ::= "FLOAT"
GROUP ::= "GROUP"
INDEX ::= "INDEX"
INNER ::= "INNER"
LIMIT ::= "LIMIT"
LOCAL ::= "LOCAL"
MERGE ::= "MERGE"
MINUS ::= "MINUS"
ORDER ::= "ORDER"
OUTER ::= "OUTER"
RIGHT ::= "RIGHT"
TABLE ::= "TABLE"
UNION ::= "UNION"
USING ::= "USING"
WHERE ::= "WHERE"
CALL ::= "CALL"
CASE ::= "CASE"
CHAR ::= "CHAR"
COPY ::= "COPY"
DATE ::= "DATE"
DATETIME ::= "DATETIME"
DESC ::= "DESC"
DROP ::= "DROP"
ELSE ::= "ELSE"
FILE ::= "FILE"
FROM ::= "FROM"
FULL ::= "FULL"
HASH ::= "HASH"
HINT ::= "HINT"
INTO ::= "INTO"
JOIN ::= "JOIN"
LEFT ::= "LEFT"
LIKE ::= "LIKE"
ILIKE ::= "ILIKE"
LOAD ::= "LOAD"
LONG ::= "LONG"
NULL ::= "NULL"
PLAN ::= "PLAN"
SHOW ::= "SHOW"
TEXT ::= "TEXT"
THEN ::= "THEN"
TIME ::= "TIME"
VIEW ::= "VIEW"
WHEN ::= "WHEN"
WITH ::= "WITH"
ADD ::= "ADD"
ALL ::= "ALL"
AND ::= "AND"
ASC ::= "ASC"
END ::= "END"
FOR ::= "FOR"
INT ::= "INT"
KEY ::= "KEY"
NOT ::= "NOT"
OFF ::= "OFF"
SET ::= "SET"
TOP ::= "TOP"
AS ::= "AS"
BY ::= "BY"
IF ::= "IF"
IN ::= "IN"
IS ::= "IS"
OF ::= "OF"
ON ::= "ON"
OR ::= "OR"
TO ::= "TO"
SECOND ::= "SECOND"
MINUTE ::= "MINUTE"
HOUR ::= "HOUR"
DAY ::= "DAY"
MONTH ::= "MONTH"
YEAR ::= "YEAR"
TRUE ::= "TRUE"
FALSE ::= "FALSE"
TRANSACTION ::= "TRANSACTION"
BEGIN ::= "BEGIN"
ROLLBACK ::= "ROLLBACK"
COMMIT ::= "COMMIT"

/* Allow =/== see https://sqlite.org/lang_expr.html#collateop */
EQUALS ::= "=="
NOTEQUALS ::= "!="
NOTEQUALS ::= "<>"
LESSEQ ::= "<="
GREATEREQ ::= ">="
CONCAT ::= "||"