Skip to content

Grammar railroad diagram #47

@mingodad

Description

@mingodad

Using https://www.bottlecaps.de/ebnf-convert/ to convert https://github.com/MelbourneDeveloper/osprey/blob/main/compiler/osprey.g4 to an EBNF understood by https://github.com/GuntherRademacher/rr that generate a nice navigable railroad diagram (see bellow with instructions at the top).

//
// EBNF to be viewd at
//    https://www.bottlecaps.de/rr/ui
//
// Copy and paste this at the url shown above in the 'Edit Grammar' tab
// then click the 'View Diagram' tab.
//
/* converted on Sun Jul 13, 2025, 19:11 (UTC+02) by antlr_4-to-w3c v0.71 which is Copyright (c) 2011-2025 by Gunther Rademacher <grd@gmx.net> */

program  ::= statement* EOF
statement
         ::= importStmt
           | letDecl
           | assignStmt
           | fnDecl
           | externDecl
           | typeDecl
           | effectDecl
           | moduleDecl
           | exprStmt
importStmt
         ::= 'import' ID ( '.' ID )*
letDecl  ::= ( 'let' | 'mut' ) ID ( ':' type )? '=' expr
assignStmt
         ::= ID '=' expr
fnDecl   ::= docComment? 'fn' ID '(' paramList? ')' ( '->' type )? effectSet? ( '=' expr | '{' blockBody '}' )
externDecl
         ::= docComment? 'extern' 'fn' ID '(' externParamList? ')' ( '->' type )?
externParamList
         ::= externParam ( ',' externParam )*
externParam
         ::= ID ':' type
paramList
         ::= param ( ',' param )*
param    ::= ID ( ':' type )?
typeDecl ::= docComment? 'type' ID ( '<' typeParamList '>' )? '=' ( unionType | recordType )
typeParamList
         ::= ID ( ',' ID )*
unionType
         ::= variant ( '|' variant )*
recordType
         ::= '{' fieldDeclarations '}'
variant  ::= ID ( '{' fieldDeclarations '}' )?
fieldDeclarations
         ::= fieldDeclaration ( ',' fieldDeclaration )*
fieldDeclaration
         ::= ID ':' type constraint?
constraint
         ::= 'where' functionCall
effectDecl
         ::= docComment? 'effect' ID '{' opDecl* '}'
opDecl   ::= ID ':' type
effectSet
         ::= '!' ( ID | '[' effectList ']' )
effectList
         ::= ID ( ',' ID )*
handlerExpr
         ::= 'handle' ID handlerArm+ 'in' expr
handlerArm
         ::= ID handlerParams? '=>' expr
handlerParams
         ::= ID+
functionCall
         ::= ID '(' argList? ')'
booleanExpr
         ::= comparisonExpr
fieldList
         ::= field ( ',' field )*
field    ::= ID ':' type
type     ::= 'fn'? '(' typeList? ')' '->' type
           | ID ( '<' typeList '>' | '[' type ']' )?
typeList ::= type ( ',' type )*
exprStmt ::= expr
expr     ::= matchExpr
matchExpr
         ::= 'match' expr '{' matchArm+ '}'
           | selectExpr
           | binaryExpr
selectExpr
         ::= 'select' '{' selectArm+ '}'
selectArm
         ::= ( pattern | '_' ) '=>' expr
binaryExpr
         ::= comparisonExpr
comparisonExpr
         ::= addExpr ( ( '==' | '!=' | '<' | '>' | '<=' | '>=' ) addExpr )*
addExpr  ::= mulExpr ( ( '+' | '-' ) mulExpr )*
mulExpr  ::= unaryExpr ( ( '*' | '/' | '%' ) unaryExpr )*
unaryExpr
         ::= ( '+' | '-' | '!' | 'await' )? pipeExpr
pipeExpr ::= callExpr ( '|>' callExpr )*
callExpr ::= primary ( ( '.' ID )* ( '(' argList? ')' )? | ( '.' ID '(' argList? ')' )+ )
argList  ::= namedArgList
           | expr ( ',' expr )*
namedArgList
         ::= namedArg ( ',' namedArg )+
namedArg ::= ID ':' expr
primary  ::= 'spawn' expr
           | 'yield' expr?
           | ( ( ( 'await' | 'recv' )? '(' | 'send' '(' expr ',' ) expr | 'perform' ID '.' ID '(' argList? ) ')'
           | 'select' selectExpr
           | handlerExpr
           | typeConstructor
           | updateExpr
           | blockExpr
           | literal
           | lambdaExpr
           | ID ( '[' INT ']' )?
typeConstructor
         ::= ID typeArgs? '{' fieldAssignments '}'
typeArgs ::= '<' typeList '>'
fieldAssignments
         ::= fieldAssignment ( ',' fieldAssignment )*
fieldAssignment
         ::= ID ':' expr
lambdaExpr
         ::= ( 'fn' '(' paramList? ')' ( '->' type )? | '|' paramList? '|' ) '=>' expr
updateExpr
         ::= ID '{' fieldAssignments '}'
blockExpr
         ::= '{' blockBody '}'
literal  ::= INT
           | STRING
           | INTERPOLATED_STRING
           | 'true'
           | 'false'
           | listLiteral
listLiteral
         ::= '[' ( expr ( ',' expr )* )? ']'
docComment
         ::= DOC_COMMENT+
moduleDecl
         ::= docComment? 'module' ID '{' moduleBody '}'
moduleBody
         ::= moduleStatement*
moduleStatement
         ::= letDecl
           | fnDecl
           | typeDecl
matchArm ::= pattern '=>' expr
pattern  ::= unaryExpr
           | ID ( '{' fieldPattern '}' | '(' pattern ( ',' pattern )* ')' | ID | ':' ( type | '{' fieldPattern '}' ) )?
           | '{' fieldPattern '}'
           | '_'
fieldPattern
         ::= ID ( ',' ID )*
blockBody
         ::= statement* expr?
_        ::= WS
           | COMMENT
          /* ws: definition */

<?TOKENS?>

INT      ::= [0-9]+
INTERPOLATED_STRING
         ::= '"' ( [^"\$] | '\' . | '$' [^{] )* ( '${' [^}]* '}' ( [^"\$] | '\' . | '$' [^{] )* )+ '"'
STRING   ::= '"' ( [^"\] | '\' . )* '"'
ID       ::= [a-zA-Z_] [a-zA-Z0-9_]*
WS       ::= [ #x9#xd#xa]+
DOC_COMMENT
         ::= '///' [^#xd#xa]*
COMMENT  ::= '//' [^#xd#xa]*
EOF      ::= $

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions