Grammar railroad diagram
mingodad opened this issue · comments
Domingo Alvarez Duarte commented
Using this script https://github.com/mingodad/plgh/blob/main/json2ebnf.js (with quickjs) and with some manual fixes we can have a navigable railroad diagram.
Copy and paste the EBNF shown bellow on https://www.bottlecaps.de/rr/ui on the tab Edit Grammar
the click on the tab View Diagram
to see/download a navigable railroad diagram.
//
// From ../tree-sitter/docs/index.md
//
//
// EBNF to generate railroad diagram at https://www.bottlecaps.de/rr/ui
//
source_file ::= ( ( _top_level_declaration | _statement ) _automatic_separator? ) *
_top_level_declaration ::= const_declaration | global_var_declaration | function_declaration | type_declaration | struct_declaration | _binded_struct_declaration | enum_declaration | interface_declaration | import_declaration | module_clause
_expression ::= empty_literal_value | int_literal | float_literal | _string_literal | rune_literal | _reserved_identifier | binded_identifier | identifier | _single_line_expression | type_initializer | map | array | fixed_array | unary_expression | binary_expression | is_expression | index_expression | slice_expression | type_cast_expression | as_type_cast_expression | call_expression | special_call_expression | fn_literal | selector_expression | parenthesized_expression | _expression_with_blocks
parenthesized_expression ::= '(' _expression ')'
unary_expression ::= ( ( ( ( '+' | '-' | '!' | '~' | '^' | '*' | '&' | '<-' ) ) ( _expression ) ) )
binary_expression ::= ( ( ( _expression ) ( ( '*' | '/' | '%' | '<<' | '>>' | '>>>' | '&' | '&^' ) ) ( _expression ) ) ) | ( ( ( _expression ) ( ( '+' | '-' | '|' | '^' ) ) ( _expression ) ) ) | ( ( ( _expression ) ( ( '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | '!in' ) ) ( _expression ) ) ) | ( ( ( _expression ) ( '&&' ) ( _expression ) ) ) | ( ( ( _expression ) ( '||' ) ( _expression ) ) )
as_type_cast_expression ::= _expression 'as' _simple_type
type_cast_expression ::= ( _simple_type ) '(' ( _expression ) ')'
call_expression ::= ( ( ( ( identifier | binded_identifier | comptime_identifier | selector_expression | comptime_selector_expression ) ) ( type_parameters? ) ( argument_list ) option_propagator? ) )
special_argument_list ::= '(' ( _simple_type | option_type ) ( ',' _expression ) ? ')'
special_call_expression ::= ( ( ( ( identifier | selector_expression ) ) ( special_argument_list ) option_propagator? ) )
comptime_identifier ::= '$' identifier
comptime_selector_expression ::= '$' ( '(' selector_expression ')' )
option_propagator ::= ( ( '?' | '!' | or_block ) )
or_block ::= 'or' block
_expression_with_blocks ::= if_expression | match_expression | select_expression | sql_expression | lock_expression | unsafe_expression | comptime_if_expression
_single_line_expression ::= ( ( pseudo_comptime_identifier | type_selector_expression | none | true | false ) )
comment ::= _comment
escape_sequence ::= ( ( ( '\' ( 'u' hex_digit hex_digit hex_digit hex_digit
| 'U' hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit
| 'x' hex_digit hex_digit
| [0-9][0-9][0-9]
| '\r?\n'
| ['"abfrntv\$\]
| '\S' ) ) ) )
none ::= 'none'
true ::= 'true'
false ::= 'false'
spread_operator ::= ( ( '...' _expression ) )
type_initializer ::= ( ( ( ( builtin_type | type_identifier | type_placeholder | generic_type | _binded_type | qualified_type | pointer_type | array_type | fixed_array_type | map_type | channel_type ) ) ( literal_value ) ) )
literal_value ::= '{' ( ( ( spread_operator | keyed_element ) ( ',' | ( '\n' | '\r' | '\r\n' ) ) ? ) * | ( element ( ',' element ) * ) ) ? '}'
element ::= _expression
keyed_element ::= ( _element_key ) ':' ( _expression )
_element_key ::= ( _field_identifier ) | type_identifier | _string_literal | int_literal | call_expression | selector_expression | type_selector_expression | index_expression
map ::= ( ( '{' ( keyed_element ( ',' | ( '\n' | '\r' | '\r\n' ) ) ? ) + '}' ) )
array ::= ( _non_empty_array )
fixed_array ::= ( ( _non_empty_array '!' ) )
_non_empty_array ::= '[' ( _expression ',' ? ) * ']'
fixed_array_type ::= '[' ( ( int_literal | identifier ) ) ']' ( _simple_type )
array_type ::= ( ( '[' ']' ( _simple_type ) ) )
variadic_type ::= '...' _simple_type
pointer_type ::= ( ( '&' _simple_type ) )
map_type ::= 'map[' ( _simple_type ) ']' ( _type )
channel_type ::= ( ( 'chan' ( _simple_type ) ) )
shared_type ::= 'shared' _simple_type
thread_type ::= 'thread' _simple_type
int_literal ::= ( ( ( '0' ( 'b' | 'B' ) '_' ? ( [01] ( '_' ? [01] ) * ) ) | ( '0' | ( [1-9] ( '_' ? ( [0-9] ( '_' ? [0-9] ) * ) ) ? ) ) | ( '0' ( 'o' | 'O' ) ? '_' ? ( /[0-7]/ ( '_' ? /[0-7]/ ) * ) ) | ( '0' ( 'x' | 'X' ) '_' ? ( hex_digit ( '_' ? hex_digit ) * ) ) ) )
float_literal ::= ( ( ( ( ( [0-9] ( '_' ? [0-9] ) * ) '.' ( [0-9] ( '_' ? [0-9] ) * ) ( ( 'e' | 'E' ) ( '+' | '-' ) ? ( [0-9] ( '_' ? [0-9] ) * ) ) ? ) | ( ( [0-9] ( '_' ? [0-9] ) * ) ( ( 'e' | 'E' ) ( '+' | '-' ) ? ( [0-9] ( '_' ? [0-9] ) * ) ) ) | ( '.' ( [0-9] ( '_' ? [0-9] ) * ) ( ( 'e' | 'E' ) ( '+' | '-' ) ? ( [0-9] ( '_' ? [0-9] ) * ) ) ? ) ) | ( '0' ( 'x' | 'X' ) ( ( '_' ? ( hex_digit ( '_' ? hex_digit ) * ) '.' ( hex_digit ( '_' ? hex_digit ) * ) ? ) | ( '_' ? ( hex_digit ( '_' ? hex_digit ) * ) ) | ( '.' ( hex_digit ( '_' ? hex_digit ) * ) ) ) ( ( 'p' | 'P' ) ( '+' | '-' ) ? ( [0-9] ( '_' ? [0-9] ) * ) ) ) ) )
rune_literal ::= ( ( '`' ( [^'\] | "'" | '"' | ( '\' ( '0' | '`' | ( 'x' hex_digit hex_digit ) | ( [0-7] [0-7] [0-7] ) | ( 'u' hex_digit hex_digit hex_digit hex_digit ) | ( 'U' hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit hex_digit ) | ( 'a' | 'b' | 'e' | 'f' | 'n' | 'r' | 't' | 'v' | '\\' | "'" | '"' ) ) ) ) '`' ) )
_string_literal ::= c_string_literal | raw_string_literal | interpreted_string_literal
c_string_literal ::= ( _c_string_opening ) ( ( _string_content ) | escape_sequence | string_interpolation | ( '$' ) ) * _string_closing
raw_string_literal ::= ( _raw_string_opening ) ( _string_content ) * _string_closing
interpreted_string_literal ::= ( _string_opening ) ( ( _string_content ) | escape_sequence | string_interpolation | ( '$' ) ) * _string_closing
string_interpolation ::= ( _braced_interpolation_opening _expression format_specifier? _interpolation_closing ) | ( _unbraced_interpolation_opening ( identifier | selector_expression ) )
format_specifier ::= ( ':' ) ( ( [gGeEfFcdoxXpsSc] ) | ( ( [+-0] ) ? int_literal ( '.' int_literal ) ? ( [gGeEfFcdoxXpsSc] ) ? ) )
_reserved_identifier ::= ( 'array' | 'string' | 'char' | 'sql' )
identifier ::= ( ( ( ( [a-zα-ωµ] | '_' ) ( ( [a-zA-Zα-ωΑ-Ωµ] | '_' ) | [0-9] ) * ) | ( '@' ( ( 'pub' ) | ( 'none' ) | ( 'const' ) | ( 'mut' ) | ( '__global' ) | ( 'fn' ) | ( 'assert' ) | ( 'as' ) | ( 'go' ) | ( 'spawn' ) | ( 'asm' ) | ( 'return' ) | ( 'type' ) | ( 'if' ) | ( 'else' ) | ( 'for' ) | ( 'in' ) | ( 'is' ) | ( 'union' ) | ( 'struct' ) | ( 'enum' ) | ( 'interface' ) | ( 'defer' ) | ( 'unsafe' ) | ( 'import' ) | ( 'match' ) | ( 'lock' ) | ( 'rlock' ) | ( 'select' ) | ( 'voidptr' ) | ( 'byteptr' ) | ( 'charptr' ) | ( 'i8' ) | ( 'i16' ) | ( 'i32' ) | ( 'int' ) | ( 'i64' ) | ( 'byte' ) | ( 'u8' ) | ( 'u16' ) | ( 'u32' ) | ( 'u64' ) | ( 'f32' ) | ( 'f64' ) | ( 'char' ) | ( 'bool' ) | ( 'string' ) | ( 'rune' ) | ( 'array' ) | ( 'map' ) | ( 'mapnode' ) | ( 'chan' ) | ( 'size_t' ) | ( 'usize' ) | ( 'isize' ) | ( 'float_literal' ) | ( 'int_literal' ) | ( 'thread' ) | ( 'IError' ) ) ) ) )
immediate_identifier ::= ( ( [a-zα-ωµ] ( ( [a-zA-Zα-ωΑ-Ωµ] | '_' ) | [0-9] | '_' ) * ) )
_old_identifier ::= ( ( ( [a-zA-Zα-ωΑ-Ωµ] | '_' ) ( ( [a-zA-Zα-ωΑ-Ωµ] | '_' ) | [0-9] ) * ) )
_mutable_prefix ::= ( ( ( 'mut' 'static' ? ) | 'shared' ) )
mutable_identifier ::= ( ( _mutable_prefix ( identifier | _reserved_identifier ) ) )
_mutable_expression_2 ::= ( ( _mutable_prefix ( selector_expression | index_expression ) ) )
mutable_expression ::= ( ( _mutable_prefix _expression ) )
binded_identifier ::= ( ( 'C' | 'JS' ) ) ( '.' ) ( ( identifier | _old_identifier ) )
identifier_list ::= ( ( ( mutable_identifier | identifier | _reserved_identifier ) ( ',' ( mutable_identifier | identifier | _reserved_identifier ) ) * ) )
expression_list ::= ( ( ( _expression | mutable_expression ) ( ',' ( _expression | mutable_expression ) ) * ) )
_expression_list_repeat1 ::= ( _expression | mutable_expression ) ( ',' ( _expression | mutable_expression ) ) +
parameter_declaration ::= ( ( mutable_identifier | identifier | _reserved_identifier ) ) ( ( _simple_type | option_type | variadic_type ) )
parameter_list ::= ( ( '(' ( parameter_declaration ( ',' parameter_declaration ) * ) ? ')' ) )
empty_literal_value ::= ( ( '{' '}' ) )
argument_list ::= '(' ( ( _expression | mutable_expression | keyed_element | spread_operator ) ( ( ',' | _automatic_separator ) ( _expression | mutable_expression | keyed_element | spread_operator ) ) * _automatic_separator? ) ? ')'
_type ::= _simple_type | option_type | result_type | multi_return_type
option_type ::= ( ( '?' ( _simple_type | multi_return_type ) ? ) )
result_type ::= ( ( '!' ( _simple_type | multi_return_type ) ? ) )
multi_return_type ::= '(' ( _simple_type ( ',' _simple_type ) * ) ')'
type_list ::= _simple_type ( ',' _simple_type ) *
_simple_type ::= builtin_type | type_identifier | type_placeholder | _binded_type | qualified_type | pointer_type | array_type | fixed_array_type | function_type | generic_type | map_type | channel_type | shared_type | thread_type
type_parameters ::= ( ( ( '<' ) ( _simple_type ( ',' _simple_type ) * ) ( '>' ) ) )
builtin_type ::= ( ( 'voidptr' | 'byteptr' | 'charptr' | 'i8' | 'i16' | 'i32' | 'int' | 'i64' | 'byte' | 'u8' | 'u16' | 'u32' | 'u64' | 'f32' | 'f64' | 'char' | 'bool' | 'string' | 'rune' | 'array' | 'map' | 'mapnode' | 'chan' | 'size_t' | 'usize' | 'isize' | 'float_literal' | 'int_literal' | 'thread' | 'IError' ) )
_binded_type ::= ( binded_identifier )
generic_type ::= ( qualified_type | type_identifier ) type_parameters
qualified_type ::= ( _module_identifier ) '.' ( type_identifier )
type_placeholder ::= ( [A-ZΑ-Ω] )
pseudo_comptime_identifier ::= '@' [A-Z][A-Z0-9_]+
type_identifier ::= ( ( [A-ZΑ-Ω] ( ( [a-zA-Zα-ωΑ-Ωµ] | '_' ) | [0-9] ) + ) )
_module_identifier ::= identifier
_field_identifier ::= identifier
_statement_list ::= ( _statement _automatic_separator? ) +
_statement ::= _simple_statement | assert_statement | continue_statement | break_statement | return_statement | asm_statement | go_statement | spawn_statement | goto_statement | labeled_statement | defer_statement | for_statement | comptime_for_statement | send_statement | block | hash_statement
_simple_statement ::= _expression | inc_statement | dec_statement | assignment_statement | short_var_declaration
inc_statement ::= _expression '++'
dec_statement ::= _expression '--'
send_statement ::= ( ( ( _expression ) '<-' ( _expression ) ) )
short_var_declaration ::= ( ( ( expression_list ) ':=' ( expression_list ) ) )
assignment_statement ::= ( expression_list ) ( ( '*=' | '/=' | '%=' | '<<=' | '>>=' | '>>>=' | '&=' | '&^=' | '+=' | '-=' | '|=' | '^=' | '=' ) ) ( expression_list )
assert_statement ::= 'assert' _expression
block ::= '{' ( _statement_list | _expression_list_repeat1 | empty_labeled_statement | ( _statement_list ( _expression_list_repeat1 | empty_labeled_statement ) ) ) ? '}'
defer_statement ::= 'defer' block
unsafe_expression ::= 'unsafe' block
overloadable_operator ::= ( '+' ) | ( '-' ) | ( '*' ) | ( '/' ) | ( '%' ) | ( '<' ) | ( '>' ) | ( '==' ) | ( '!=' ) | ( '<=' ) | ( '>=' )
exposed_variables_list ::= '[' expression_list ']'
function_declaration ::= ( ( ( attribute_list? ) 'pub' ? 'fn' ( parameter_list? ) ( exposed_variables_list? ) ( ( binded_identifier | identifier | overloadable_operator ) ) ( type_parameters? ) ( ( parameter_list | type_only_parameter_list ) ) ( _type? ) ( block? ) ) )
function_type ::= ( ( 'fn' ( ( parameter_list | type_only_parameter_list ) ) ( _type? ) ) )
type_only_parameter_list ::= '(' ( type_parameter_declaration ( ',' type_parameter_declaration ) * ) ? ')'
type_parameter_declaration ::= 'mut' ? ( ( _simple_type | option_type | variadic_type ) )
fn_literal ::= ( ( 'fn' ( exposed_variables_list? ) ( parameter_list ) ( _type? ) ( block ) ( argument_list? ) ) )
global_var_declaration ::= '__global' ( _global_var_spec | global_var_type_initializer | ( '(' ( ( _global_var_spec | global_var_type_initializer ) ( '\n' | '\r' | '\r\n' ) ) * ')' ) )
_global_var_spec ::= const_spec
global_var_type_initializer ::= ( identifier ) ( _type )
const_declaration ::= 'pub' ? 'const' ( const_spec | ( '(' ( const_spec ( '\n' | '\r' | '\r\n' ) ) + ')' ) )
const_spec ::= ( ( identifier | _old_identifier ) ) '=' ( _expression )
asm_statement ::= 'asm' identifier _content_block
sql_expression ::= ( ( 'sql' identifier? _content_block ) )
_content_block ::= '{' ( ( [^{}]+ ) ) '}'
break_statement ::= ( ( 'break' identifier? ) )
continue_statement ::= ( ( 'continue' identifier? ) )
return_statement ::= ( ( 'return' expression_list? ) )
type_declaration ::= 'pub' ? 'type' ( ( type_identifier | builtin_type ) ) ( type_parameters? ) '=' ( sum_type_list )
sum_type_list ::= _simple_type ( '|' _simple_type ) *
go_statement ::= 'go' _expression
spawn_statement ::= 'spawn' _expression
goto_statement ::= 'goto' identifier
labeled_statement ::= ( identifier ) ':' _statement
empty_labeled_statement ::= ( ( ( identifier ) ':' ) )
for_statement ::= 'for' ( for_in_operator | cstyle_for_clause | _expression ) ? ( block )
comptime_for_statement ::= '$for' for_in_operator ( block )
for_in_operator ::= ( ( ( ( _expression | identifier_list ) ) 'in' ( ( _definite_range | _expression ) ) ) )
_definite_range ::= ( ( ( _expression ) ( '..' | '...' ) ( _expression ) ) )
_range ::= ( ( ( _expression? ) '..' ( _expression? ) ) )
selector_expression ::= ( ( ( ( _expression | comptime_identifier ) ) '.' ( ( identifier | type_identifier | type_placeholder | _reserved_identifier | comptime_identifier | comptime_selector_expression ) ) ) )
index_expression ::= ( ( ( _expression ) '[' ( _expression ) ']' option_propagator? ) )
slice_expression ::= ( ( ( _expression ) '[' _range ']' ) )
cstyle_for_clause ::= ( ( ( _simple_statement? ) ';' ( _expression? ) ';' ( _simple_statement? ) ) )
comptime_if_expression ::= '$if' ( ( _expression '?' ? ) ) ( block ) ( '$else' ( ( block | comptime_if_expression ) ) ) ?
if_expression ::= 'if' ( ( _expression ) | ( short_var_declaration ) ) ( block ) ( 'else' ( ( block | if_expression ) ) ) ?
is_expression ::= ( ( ( ( type_placeholder | mutable_identifier | _mutable_expression_2 | mutable_expression | _expression ) ) ( 'is' | '!is' ) ( ( option_type | _simple_type | none ) ) ) )
attribute_spec ::= ( ( ( 'if' identifier '?' ? ) | 'unsafe' | identifier | interpreted_string_literal | ( ( ( 'unsafe' | identifier ) ) ':' ( ( _string_literal | identifier ) ) ) ) )
attribute_declaration ::= '[' ( attribute_spec ( ';' attribute_spec ) * ) ']'
attribute_list ::= ( attribute_declaration ( '\n' | '\r' | '\r\n' ) ? ) +
struct_declaration ::= ( attribute_list? ) 'pub' ? ( 'struct' | 'union' ) ( ( ( type_identifier | builtin_type | generic_type ) ) ) struct_field_declaration_list
struct_field_declaration_list ::= '{' ( ( struct_field_scope | struct_field_declaration ) ( '\n' | '\r' | '\r\n' ) ? ) * '}'
struct_field_scope ::= ( 'pub' | 'mut' | ( 'pub' 'mut' ) | '__global' ) ( ':' )
struct_field_declaration ::= ( ( ( ( _field_identifier ) ( ( _simple_type | option_type ) ) ( attribute_declaration? ) ( '=' ( _expression ) ) ? ( '\n' | '\r' | '\r\n' ) ? ) | ( ( ( type_identifier | qualified_type ) ( '\n' | '\r' | '\r\n' ) ? ) ) ) )
_binded_struct_declaration ::= ( attribute_list? ) 'pub' ? ( 'struct' | 'union' ) ( ( _binded_type ) ) _binded_struct_field_declaration_list
_binded_struct_field_declaration_list ::= '{' ( ( struct_field_scope | _binded_struct_field_declaration ) ( '\n' | '\r' | '\r\n' ) ? ) * '}'
_binded_struct_field_declaration ::= ( ( ( ( _field_identifier | _old_identifier ) ) ( ( _simple_type | option_type ) ) ( attribute_declaration? ) ( '=' ( _expression ) ) ? ( '\n' | '\r' | '\r\n' ) ? ) )
enum_declaration ::= attribute_list? 'pub' ? 'enum' ( type_identifier ) enum_member_declaration_list
enum_member_declaration_list ::= '{' ( enum_member ( '\n' | '\r' | '\r\n' ) ? ) * ? '}'
enum_member ::= ( identifier ) ( '=' ( _expression ) ) ?
type_selector_expression ::= ( ( type_placeholder | type_identifier ) ? ) '.' ( ( _reserved_identifier | identifier ) )
interface_declaration ::= ( attribute_list? ) 'pub' ? 'interface' ( ( type_identifier | generic_type ) ) interface_spec_list
interface_spec_list ::= '{' ( ( struct_field_declaration | interface_spec | interface_field_scope ) ( '\n' | '\r' | '\r\n' ) ? ) * ? '}'
interface_field_scope ::= 'mut' ( ':' )
interface_spec ::= ( ( ( _field_identifier ) ( ( parameter_list | type_only_parameter_list ) ) ( _type? ) ) )
hash_statement ::= '#' ( [^\r?\n]+ ) ( '\n' | '\r' | '\r\n' )
module_clause ::= ( attribute_list? ) 'module' ' ' immediate_identifier
import_declaration ::= ( ( 'import' ' ' ( import_path ) ( ' ' ( ( import_alias ) | ( import_symbols ) ) ) ? ) )
import_path ::= ( ( ( [a-zA-Zα-ωΑ-Ωµ] | '_' ) ( ( [a-zA-Zα-ωΑ-Ωµ] | '_' ) | [0-9] | '.' ) * ) )
import_symbols ::= ( '{' ) import_symbols_list '}'
import_symbols_list ::= ( identifier | type_identifier ) ( ',' ( identifier | type_identifier ) ) *
import_alias ::= 'as' ' ' ( immediate_identifier )
match_expression ::= 'match' ( ( _expression | mutable_expression ) ) '{' expression_case* default_case? '}'
case_list ::= ( _expression | _simple_type | _definite_range ) ( ',' ( _expression | _simple_type | _definite_range ) ) *
expression_case ::= ( case_list ) ( block )
default_case ::= 'else' ( block )
select_expression ::= 'select' ( expression_list? ) '{' select_branch* select_default_branch? '}'
select_branch ::= short_var_declaration block
select_default_branch ::= ( ( ( '>' ? _expression ) ) | 'else' ) block
lock_expression ::= ( 'lock' | 'rlock' ) ( expression_list? ) ( block )
// To make easy conversion
hex_digit ::= [a-fA-F0-9]
JalonSolov commented
Try https://blog.vosca.dev/meet-v-analyzer/ instead, now that it is released.