Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grammar railroad diagram #7250

Open
mingodad opened this issue May 16, 2023 · 2 comments
Open

Grammar railroad diagram #7250

mingodad opened this issue May 16, 2023 · 2 comments
Assignees
Labels
enhancement help wanted Issue not worked on by OTP; help wanted from the community team:VM Assigned to OTP team VM

Comments

@mingodad
Copy link

After manually edit https://github.com/erlang/otp/blob/master/lib/compiler/src/core_parse.yrl to convert it to an EBNF understood by https://www.bottlecaps.de/rr/ui to generate a navigable railroad diagram (basically replace %% by //%%, -> by ::= and remove code after :).

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 https://github.com/erlang/otp/blob/master/lib/compiler/src/core_parse.yrl
//%% -*-Erlang-*-
//%% %CopyrightBegin%
//%%
//%% Copyright Ericsson AB 1999-2021. All Rights Reserved.
//%%
//%% Licensed under the Apache License, Version 2.0 (the "License");
//%% you may not use this file except in compliance with the License.
//%% You may obtain a copy of the License at
//%%
//%%     http://www.apache.org/licenses/LICENSE-2.0
//%%
//%% Unless required by applicable law or agreed to in writing, software
//%% distributed under the License is distributed on an "AS IS" BASIS,
//%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//%% See the License for the specific language governing permissions and
//%% limitations under the License.
//%%
//%% %CopyrightEnd%
//%%
//%% Core Erlang YECC parser grammar

//%% Have explicit productions for annotated phrases named anno_XXX.
//%% This just does an XXX and adds the annotation.

//Expect 0.
//
//Nonterminals
//
//module_definition module_export module_attribute module_defs
//exported_names exported_name
//attribute_list attribute
//function_definition function_definitions
//
//constant constants atomic_constant tuple_constant cons_constant tail_constant
//other_pattern atomic_pattern tuple_pattern cons_pattern tail_pattern
//binary_pattern segment_patterns segment_pattern
//
//expression single_expression
//literal literals atomic_literal tuple_literal cons_literal tail_literal fun_literal
//nil tuple cons tail
//binary segments segment
//
//let_expr let_vars letrec_expr case_expr fun_expr
//function_name
//application_expr call_expr primop_expr arg_list
//receive_expr timeout try_expr
//sequence catch_expr
//variable clause clause_pattern
//
//map_expr anno_map_expr map_pairs anno_map_pair map_pair map_pair_assoc map_pair_exact
//map_pattern map_pair_patterns map_pair_pattern
//
//annotation anno_atom anno_fun anno_expression anno_expressions
//anno_variable anno_variables anno_pattern anno_patterns
//anno_function_name
//anno_literal
//anno_segment anno_segment_pattern
//anno_clause anno_clauses.
//
//Terminals
//
////%% Separators
//
//'(' ')' '{' '}' '[' ']' '|' ',' '->' '=' '/' '<' '>' ':' '-|' '#'
//'~' '=>' ':='
//
////%% Keywords (atoms are assumed to always be single-quoted).
//
//'module' 'attributes' 'do' 'let' 'in' 'letrec'
//'apply' 'call' 'primop'
//'case' 'of' 'end' 'when' 'fun' 'try' 'catch' 'receive' 'after'
//
////%% Literal tokens (provided by the tokeniser):
//
//char integer float atom string var.
//
////%% Literal tokens NOT provided by the tokenise:
//
//nil ::= '[' ']' : {nil,tok_line('$1')}.
//
////%% Declare the start rule for parsing
//
//Rootsymbol module_definition.


//%% Grammar

module_definition ::=
    'module' atom module_export module_attribute module_defs 'end'
module_definition ::=
    '(' 'module' atom module_export module_attribute module_defs 'end'
	'-|' annotation ')'

module_export ::= '[' ']'
module_export ::= '[' exported_names ']'

exported_names ::= exported_name ',' exported_names
exported_names ::= exported_name

exported_name ::= anno_function_name

module_attribute ::= 'attributes' '[' ']'
module_attribute ::= 'attributes' '[' attribute_list ']'

attribute_list ::= attribute ',' attribute_list
attribute_list ::= attribute

attribute ::= anno_atom '=' anno_literal

anno_atom ::= atom
anno_atom ::= '(' atom '-|' annotation ')'

anno_literal ::= literal
anno_literal ::= '(' literal '-|' annotation ')'

module_defs ::= function_definitions

annotation ::= '[' ']'
annotation ::= '[' constants ']'

function_definitions ::=
    function_definition function_definitions
function_definitions ::=
    '$empty'

function_definition ::=
    anno_function_name '=' anno_fun

anno_fun ::= '(' fun_expr '-|' annotation ')'
anno_fun ::= fun_expr

//%% Constant terms for annotations and attributes.
//%%  These are represented by straight unabstract Erlang.

constant ::= atomic_constant
constant ::= tuple_constant
constant ::= cons_constant

constants ::= constant ',' constants
constants ::= constant

atomic_constant ::= char
atomic_constant ::= integer
atomic_constant ::= float
atomic_constant ::= atom
atomic_constant ::= string
atomic_constant ::= nil

tuple_constant ::= '{' '}'
tuple_constant ::= '{' constants '}'

cons_constant ::= '[' constant tail_constant

tail_constant ::= ']'
tail_constant ::= '|' constant ']'
tail_constant ::= ',' constant tail_constant

//%% Patterns
//%%  We have to be a little sneaky here as we would like to be able to
//%%  do:
//%%  V = {a}
//%%  ( V = {a} -| <anno> )
//%%  ( V -| <anno> ) = {a}
//%%  V = ( {a} -| <anno> )
//%%  ( ( V -| <anno> ) = ( {a} -| <anno> ) -| <anno> )

anno_pattern ::= '(' other_pattern '-|' annotation ')'
anno_pattern ::= other_pattern
anno_pattern ::= anno_variable

anno_patterns ::= anno_pattern ',' anno_patterns
anno_patterns ::= anno_pattern

other_pattern ::= atomic_pattern
other_pattern ::= tuple_pattern
other_pattern ::= map_pattern
other_pattern ::= cons_pattern
other_pattern ::= binary_pattern
other_pattern ::= anno_variable '=' anno_pattern

atomic_pattern ::= atomic_literal

tuple_pattern ::= '{' '}'
tuple_pattern ::= '{' anno_patterns '}'

map_pattern ::= '~' '{' '}' '~'
map_pattern ::= '~' '{' map_pair_patterns '}' '~'
map_pattern ::= '~' '{' map_pair_patterns '|' anno_map_expr '}' '~'

map_pair_patterns ::= map_pair_pattern
map_pair_patterns ::= map_pair_pattern ',' map_pair_patterns

map_pair_pattern ::= anno_expression ':=' anno_pattern
map_pair_pattern ::= '(' anno_expression ':=' anno_pattern '-|' annotation ')'

cons_pattern ::= '[' anno_pattern tail_pattern

tail_pattern ::= ']'
tail_pattern ::= '|' anno_pattern ']'
tail_pattern ::= ',' anno_pattern tail_pattern

binary_pattern ::= '#' '{' '}' '#'
binary_pattern ::= '#' '{' segment_patterns '}' '#'

segment_patterns ::= anno_segment_pattern ',' segment_patterns
segment_patterns ::= anno_segment_pattern

anno_segment_pattern ::= segment_pattern
anno_segment_pattern ::= '(' segment_pattern '-|' annotation ')'

segment_pattern ::= '#' '<' anno_pattern '>' '(' anno_expressions ')'

variable ::= var

anno_variables ::= anno_variable ',' anno_variables
anno_variables ::= anno_variable

anno_variable ::= variable
anno_variable ::= '(' variable '-|' annotation ')'

//%% Expressions
//%%  Must split expressions into two levels as nested value expressions
//%%  are illegal.

anno_expression ::= expression
anno_expression ::= '(' expression '-|' annotation ')'

anno_expressions ::= anno_expression ',' anno_expressions
anno_expressions ::= anno_expression

expression ::= '<' '>'
expression ::= '<' anno_expressions '>'
expression ::= single_expression

single_expression ::= atomic_literal
single_expression ::= tuple
single_expression ::= cons
single_expression ::= binary
single_expression ::= variable
single_expression ::= function_name
single_expression ::= fun_literal
single_expression ::= fun_expr
single_expression ::= let_expr
single_expression ::= letrec_expr
single_expression ::= case_expr
single_expression ::= receive_expr
single_expression ::= application_expr
single_expression ::= call_expr
single_expression ::= primop_expr
single_expression ::= try_expr
single_expression ::= sequence
single_expression ::= catch_expr
single_expression ::= map_expr

literal ::= atomic_literal
literal ::= tuple_literal
literal ::= cons_literal

literals ::= literal ',' literals
literals ::= literal

atomic_literal ::= char
atomic_literal ::= integer
atomic_literal ::= float
atomic_literal ::= atom
atomic_literal ::= string
atomic_literal ::= nil

tuple_literal ::= '{' '}'
tuple_literal ::= '{' literals '}'

cons_literal ::= '[' literal tail_literal

tail_literal ::= ']'
tail_literal ::= '|' literal ']'
tail_literal ::= ',' literal tail_literal

fun_literal ::= 'fun' atom ':' atom '/' integer

tuple ::= '{' '}'
tuple ::= '{' anno_expressions '}'

map_expr ::= '~' '{' '}' '~'
map_expr ::= '~' '{' map_pairs '}' '~'
map_expr ::= '~' '{' map_pairs '|' anno_variable '}' '~'
map_expr ::= '~' '{' map_pairs '|' anno_map_expr '}' '~'

anno_map_expr ::= map_expr
anno_map_expr ::= '(' map_expr '-|' annotation ')'

map_pairs ::= anno_map_pair
map_pairs ::= anno_map_pair ',' map_pairs

anno_map_pair ::= map_pair
anno_map_pair ::= '(' map_pair '-|' annotation ')'

map_pair ::= map_pair_assoc
map_pair ::= map_pair_exact

map_pair_assoc ::= anno_expression '=>' anno_expression
map_pair_exact ::= anno_expression ':=' anno_expression

cons ::= '[' anno_expression tail

tail ::= ']'
tail ::= '|' anno_expression ']'
tail ::= ',' anno_expression tail

binary ::= '#' '{' '}' '#'
binary ::= '#' '{' segments '}' '#'

segments ::= anno_segment ',' segments
segments ::= anno_segment

anno_segment ::= segment
anno_segment ::= '(' segment '-|' annotation ')'

segment ::= '#' '<' anno_expression '>' '(' anno_expressions ')'

function_name ::= atom '/' integer

anno_function_name ::= function_name
anno_function_name ::= '(' function_name '-|' annotation ')'

let_vars ::= anno_variable
let_vars ::= '<' '>'
let_vars ::= '<' anno_variables '>'

sequence ::= 'do' anno_expression anno_expression

fun_expr ::= 'fun' '(' ')' '->' anno_expression
fun_expr ::= 'fun' '(' anno_variables ')' '->' anno_expression

let_expr ::= 'let' let_vars '=' anno_expression 'in' anno_expression

letrec_expr ::= 'letrec' function_definitions 'in' anno_expression

case_expr ::= 'case' anno_expression 'of' anno_clauses 'end'

anno_clauses ::= anno_clause anno_clauses
anno_clauses ::= anno_clause

anno_clause ::= clause
anno_clause ::= '(' clause '-|' annotation ')'

clause ::= clause_pattern 'when' anno_expression '->' anno_expression

clause_pattern ::= anno_pattern
clause_pattern ::= '<' '>'
clause_pattern ::= '<' anno_patterns '>'

application_expr ::= 'apply' anno_expression arg_list

call_expr ::=
    'call' anno_expression ':' anno_expression arg_list

primop_expr ::= 'primop' anno_expression arg_list

arg_list ::= '(' ')'
arg_list ::= '(' anno_expressions ')'

try_expr ::=
    'try' anno_expression 'of' let_vars '->' anno_expression
	'catch' let_vars '->' anno_expression

catch_expr ::= 'catch' anno_expression

receive_expr ::= 'receive' timeout
receive_expr ::= 'receive' anno_clauses timeout

timeout ::=
    'after' anno_expression '->' anno_expression

//%% ====================================================================== //%%
@IngelaAndin IngelaAndin added the team:VM Assigned to OTP team VM label May 17, 2023
@jhogberg jhogberg added the help wanted Issue not worked on by OTP; help wanted from the community label May 22, 2023
@jhogberg
Copy link
Contributor

Thanks, do you want this diagram to be part of the documentation? Feel free to make a PR that adds it.

@mingodad
Copy link
Author

Ideally the parser generator tool should have an option to output a naked grammar and also an EBNF grammar like the one shown above (something like I did for bison/yacc/lemon here https://github.com/mingodad/lalr-parser-test ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement help wanted Issue not worked on by OTP; help wanted from the community team:VM Assigned to OTP team VM
Projects
None yet
Development

No branches or pull requests

3 participants