chklauser / prx

Prexonite, a .NET hosted scripting language with a focus on meta-programming and embedded DSLs
prexonite.org
BSD 3-Clause "New" or "Revised" License
3 stars 0 forks source link

Grammar railroad diagram #148

Open mingodad opened 3 years ago

mingodad commented 3 years ago

Looking for people using CocoR I found this project and I've done a experimental tool to convert CocoR grammars to a kind of EBNF understood by https://www.bottlecaps.de/rr/ui to generate railroad diagrams see bellow the converted and with some hand made changes of myamalgamation_of_peroxite.atg to allow view it at https://www.bottlecaps.de/rr/ui the order of the rules could be changed to a better view of the railroad diagrams. Copy and paste the EBNF bellow on https://www.bottlecaps.de/rr/ui tab Edit Grammar then switch to the tab View Diagram.

Cheers !

//"/*" "*/" "//" lf cr  '+' lf  '+' tab
Prexonite ::=  ( InterpreterLine  )? DeclarationLevel EOF
InterpreterLine ::= interpreterline
DeclarationLevel ::=  (  ( GlobalVariableDefinition  | MetaAssignment  )? SYNC semicolon  |  ( Declaration2  | GlobalCode  | BuildBlock  | FunctionDefinition  | NamespaceImport  | NamespaceDeclaration  )  )*
MetaAssignment ::=  ( is  ( not  )? GlobalId  | not GlobalId  | GlobalId  ( enabled  | disabled  | MetaExpr  |  )  | add MetaExpr to GlobalId  )
MetaExpr ::= Boolean  | Integer  | Real  |  ( String  | NsQualifiedId  | GlobalQualifiedId  )  ( div Version  )?  | lbrace  ( MetaExpr  ( comma  ( MetaExpr  |  )  )*  )? rbrace
GlobalVariableDefinition ::=  ( var  | ref  )  ( GlobalId  ( GlobalVariableAliasList  )?  | GlobalVariableAliasList  )  ( lbrack  ( MetaAssignment  ( semicolon  ( MetaAssignment  )?  )*  )? rbrack  )?  ( assign Expr  )?
GlobalVariableAliasList ::= as GlobalId  ( comma  ( GlobalId  )?  )*
SymbolPrefix ::= ref  | pointer
EntityFactory ::=  ( var  | function  | command  | macro  ( function  | command  | var  )  |  )
Declaration2 ::= SYNC declare  (  ( SymbolPrefix  )* EntityFactory  ( colon  )? DeclarationInstance2  ( comma  ( DeclarationInstance2  )?  )* semicolon  | lbrace  ( uusing ModuleName  )?  (  ( SymbolPrefix  )* EntityFactory colon DeclarationInstance2  ( comma  ( DeclarationInstance2  )?  )*  )* rbrace  | lpar  ( MExprBasedDeclaration  ( comma  ( MExprBasedDeclaration  )?  )*  )? rpar  ( semicolon  )?  )
MExprBasedDeclaration ::= Id assign MExpr
MessageDirective ::= lpar  ( null  | String  )  ( colon  ( null  | String colon Integer colon Integer  )  )? comma String comma SymbolDirective rpar
SymbolDirective ::= null  |  ( ref  | pointer  ) SymbolDirective  | id MessageDirective  | id MessageDirective  | id MessageDirective  | Id  ( div ModuleName  )?
DeclarationInstance2 ::= SymbolDirective  ( as Id  )?
ModuleName ::= Id  ( div Version  )?
BuildBlock ::= SYNC build  ( does  )? StatementBlock
GlobalCode ::= lbrace  ( Statement  )* rbrace
FunctionAliasList ::= as Id  ( comma  ( Id  )?  )*
FunctionDefinition ::=  ( lazy  ( function  )?  | function  | coroutine  | macro  ( function  )?  )  ( Id  ( FunctionAliasList  )?  | FunctionAliasList  )  ( lpar  ( FormalArg  ( comma  ( FormalArg  |  )  )*  )? rpar  | FormalArg  (  ( comma  )? FormalArg  )*  )?  ( lbrack  ( MetaAssignment  ( semicolon  ( MetaAssignment  )?  )*  )? rbrack  )?  ( namespace ImportContextualKeyword NsTransferSpec  ( comma NsTransferSpec  )*  )?  ( does StatementBlock  | lbrace  ( Statement  )* rbrace  | implementation StatementBlock  |  ( assign  | implementation  ) Expr semicolon  )
FormalArg ::=  ( var  | ref  )? Id
GlobalId ::= id  | anyId String
GlobalQualifiedId ::= GlobalId  | ns  ( ns  )* GlobalId
NsQualifiedId ::= NsQualifiedIdImpl
NsTransferSource ::= NsQualifiedIdImpl  | GlobalQualifiedId
NsQualifiedIdImpl ::= GlobalId  ( dot  ( DotId  | timessym  | times  )  )*
NsTransferDirective ::=  ( times  | GlobalId  ( implementation GlobalId  |  )  | not GlobalId  )
NsTransferDirectiveGroup ::=  ( lpar  ( NsTransferDirective  ( comma  ( NsTransferDirective  )?  )*  )? rpar  | timessym  )
NsTransferSpec ::= NsTransferSource  ( NsTransferDirectiveGroup  |  )
ImportContextualKeyword ::= GlobalId
NamespaceImport ::= namespace ImportContextualKeyword NsTransferSpec  ( comma  ( NsTransferSpec  )?  )* semicolon
NamespaceDeclaration ::= namespace  ( NsQualifiedId  | GlobalQualifiedId  )  ( ImportContextualKeyword  ( NsTransferDirectiveGroup  |  ( NsTransferSpec  )?  )  ( comma  ( NsTransferSpec  )?  )*  )? lbrace DeclarationLevel rbrace  ( export  (  ( NsTransferDirectiveGroup  | dot times  )  (  ( comma NsTransferSpec  )* semicolon  )?  | NsTransferSpec semicolon  )  |  )
StatementBlock ::= Statement
Statement ::=  ( ExplicitLabel  | StructureStatement  |  ( SimpleStatement  )? semicolon  | StructureStatement  )  ( and Statement  )*
SimpleStatement ::= ExplicitGoTo  | GetSetComplex  | Return  | Throw  | LetBindingStmt
StructureStatement ::= asm AsmStatementBlock  | Condition  | Declaration2  | WhileLoop  | ForLoop  | ForeachLoop  | NestedFunction  | TryCatchFinally  | Using  | lbrace  ( Statement  )* rbrace
GetSetComplex ::= PrimaryForGetSetComplex  ( GetSetExtension  )*  (  |  ( inc  | dec  | Assignment  | AppendRightTermination  ( AppendRightTermination  )*  )  )
AppendRightTermination ::= appendright GetCall
GetSetExtension ::= dot Arguments  | dot DotId Arguments  | lbrack  ( Expr  ( WEAK comma Expr  )*  )? rbrack
GetInitiator ::=  ( SymbolicUsage  | VariableDeclaration  | StaticCall  | lpar Expr  ( comma Expr  )* rpar  ( GetSetExtension  | appendright GetCall  )  )  | pointer  ( pointer  )* Id  | question  ( Integer  )?
VariableDeclaration ::=  ( new  )?  ( static  ( ref  )*  ( var  )?  |  ( var  | ref  )  (  ( var  | ref  )  )*  )  ( new  )? Id
SymbolicUsage ::= Id Arguments
StaticCall ::= ExplicitTypeExpr dot DotId Arguments
ExplicitLabel ::=  ( Id colon  | lid  )
ExplicitGoTo ::= goto Id
Assignment ::=  (  (  ( assign  )  | plus assign  | minus assign  | times assign  | div assign  | bitAnd assign  | bitOr assign  | coalescence assign  ) Expr  |  ( tilde assign  ) TypeExpr  )
Condition ::=  ( if  | unless  ) lpar Expr rpar StatementBlock  ( else StatementBlock  )?
WhileLoop ::=  (  ( while  | until  ) lpar Expr rpar StatementBlock  | do StatementBlock  ( while  | until  ) lpar Expr rpar  )
ForLoop ::= for lpar StatementBlock  ( do StatementBlock  ( while  | until  ) Expr  |  ( while  | until  )? Expr semicolon SimpleStatement  ( semicolon  )?  ) rpar StatementBlock
ForeachLoop ::= foreach lpar GetCall in Expr rpar StatementBlock
GetCall ::= GetInitiator  ( GetSetExtension  )*
Return ::=  (  ( return  | yield  )  ( Expr  | assign Expr  )?  | break  | continue  )
NestedFunction ::= FunctionDefinition
LetBindingStmt ::= let LetBinder  ( comma LetBinder  )*
LetBinder ::= Id  ( assign LazyExpression  )?
TryCatchFinally ::= try lbrace  ( Statement  )* rbrace  ( catch  ( lpar GetCall rpar  |  ) lbrace  ( Statement  )* rbrace  ( finally lbrace  ( Statement  )* rbrace  )?  | finally lbrace  ( Statement  )* rbrace  ( catch  ( lpar GetCall rpar  |  ) lbrace  ( Statement  )* rbrace  )?  )?
Throw ::= ThrowExpression
Using ::= uusing lpar Expr rpar StatementBlock
Arguments ::=  ( lpar  ( Expr  ( comma  ( Expr  |  )  )*  )? rpar  )?  ( appendleft  ( lpar  ( Expr  ( comma Expr  )*  )? rpar  | Expr  )  )?
Expr ::= AtomicExpr  |  ( if  | unless  ) lpar Expr rpar Expr else Expr
AtomicExpr ::= AppendRightExpr  ( then AppendRightExpr  )*
AppendRightExpr ::= KeyValuePairExpr  ( appendright GetCall  )*
KeyValuePairExpr ::= OrExpr  ( colon KeyValuePairExpr  )?
OrExpr ::= AndExpr  ( or OrExpr  )?
AndExpr ::= DeltaExpr  ( and AndExpr  )?
DeltaExpr ::= BitOrExpr  (  ( deltaleft  | deltaright  )  ( BitOrExpr  |  )  )*
BitOrExpr ::= BitXorExpr  ( bitOr BitXorExpr  )*
BitXorExpr ::= BitAndExpr  ( xor BitAndExpr  )*
BitAndExpr ::= NotExpr  ( bitAnd NotExpr  )*
NotExpr ::=  ( not  )? EqlExpr
EqlExpr ::= RelExpr  (  ( eq  | ne  ) RelExpr  )*
RelExpr ::= CoalExpr  (  ( lt  | le  | gt  | ge  ) CoalExpr  )*
CoalExpr ::= AddExpr  ( coalescence AddExpr  )*
AddExpr ::= MulExpr  (  ( plus  | minus  ) MulExpr  )*
MulExpr ::= PowExpr  (  ( times  | div  | mod  ) PowExpr  )*
PowExpr ::= AssignExpr  ( pow AssignExpr  )*
AssignExpr ::= PostfixUnaryExpr  (  (  ( assign  | plus assign  | minus assign  | times assign  | div assign  | bitAnd assign  | bitOr assign  | coalescence assign  | deltaleft assign  | deltaright assign  ) Expr  |  ( tilde assign  ) TypeExpr  )  |  )
PostfixUnaryExpr ::= PrefixUnaryExpr  ( tilde TypeExpr  | is  ( not  )? TypeExpr  | inc  | dec  | GetSetExtension  )*
PrefixUnaryExpr ::=  ( plus  | minus  | times  | inc  | dec  | deltaleft  | deltaright  )* Primary
Primary ::= LambdaExpression  | lpar Expr rpar  | HashLiteral  | CoroutineCreation  | LoopExpr  | ThrowExpression  | LazyExpression  | PrimaryForGetSetComplex  | LPopExpr lpar Expr rpar
PrimaryForGetSetComplex ::= Constant  | ThisExpression  | ListLiteral  | ObjectCreation  | asm lpar  ( AsmInstruction  )* rpar  | GetInitiator
Constant ::= Integer  | Real  | Boolean  | String  | Null
ListLiteral ::= lbrack  ( Expr  ( comma  ( Expr  |  )  )*  )? rbrack
HashLiteral ::= lbrace  ( Expr  ( comma  ( Expr  |  )  )*  )? rbrace
LoopExpr ::=  ( WhileLoop  | ForLoop  | ForeachLoop  )
ObjectCreation ::= new TypeExpr Arguments
CoroutineCreation ::= coroutine Expr  ( for Arguments  )?
LambdaExpression ::=  ( FormalArg  | lpar  ( FormalArg  ( comma FormalArg  )*  )? rpar  ) implementation  ( lbrace  ( Statement  )* rbrace  | Expr  )
LazyExpression ::= lazy  ( lbrace  ( Statement  )* rbrace  | Expr  )
ThrowExpression ::= throw Expr
ThisExpression ::= this
ExplicitTypeExpr ::= tilde PrexoniteTypeExpr  | ClrTypeExpr
TypeExpr ::= PrexoniteTypeExpr  | ClrTypeExpr
ClrTypeExpr ::=  ( doublecolon  | ns  )  ( ns  )* Id
PrexoniteTypeExpr ::=  ( Id  | null  )  ( lt  ( TypeExprElement  ( comma TypeExprElement  )*  )? gt  )?
TypeExprElement ::= Constant  | ExplicitTypeExpr  | lpar Expr rpar
AsmStatementBlock ::= lbrace  ( AsmInstruction  )* rbrace
AsmInstruction ::=  ( var  | ref  ) AsmId  ( comma AsmId  )*  | AsmId  ( dot AsmId  )?  | AsmId  ( dot AsmId  )?  | AsmId AsmId  | AsmId  ( plus AsmId  )?  | AsmId dot Integer comma Integer  |  ( at  )? AsmId dot Integer Integer  | AsmId  | AsmId dot AsmId SignedReal  | AsmId dot AsmId Boolean  | AsmId  ( dot AsmId  )? SignedInteger  | AsmId  ( dot AsmId  )?  ( AsmId  | Integer  )  | AsmId  ( dot AsmId  )? AsmId  |  ( at  )? AsmId  ( dot Integer  |  ) AsmId  |  ( at  )? AsmId  ( dot Integer  |  )  |  ( at  )? AsmId  ( dot Integer  |  ) AsmQualid  | AsmId
AsmId ::= String  | Id  |  ( mod  | is  | not  | return  | in  | to  | continue  | break  | or  | and  | xor  | goto  | null  | else  | if  | unless  | new  | while  | until  | for  | foreach  | command  | as  | try  | throw  )
AsmQualid ::= AsmId
Id ::= GlobalId  |  ( enabled  | disabled  | build  | add  )
DotId ::= GlobalId  |  ( enabled  | disabled  | build  | add  | declare  | function  | command  | build  | ref  | var  | mod  | true  | false  | is  | as  | not  | asm  | return  | in  | to  | continue  | yield  | break  | or  | and  | xor  | static  | goto  | if  | unless  | else  | new  | coroutine  | from  | do  | does  | until  | while  | for  | foreach  | try  | catch  | try  | finally  | throw  | then  | uusing  | macro  | lazy  | let  | method  | this  | namespace  | export  )
Boolean ::= true  | false
Integer ::= integer
SignedInteger ::=  ( plus  | minus  )? Integer
Real ::=  ( real  | realLike  )
Version ::=  ( realLike  | version  )
SignedReal ::=  ( plus  | minus  )?  ( Real  | Integer  )
String ::= string
Null ::= null
MId ::=  ( var  | ref  | true  | false  | mod  | is  | as  | not  | function  | command  | asm  | declare  | build  | return  | in  | to  | continue  | break  | yield  | or  | and  | xor  | label  | goto  | static  | if  | unless  | else  | new  | coroutine  | from  | do  | does  | while  | until  | for  | foreach  | try  | catch  | finally  | throw  | then  | uusing  | macro  | lazy  | let  | method  | this  | bitAnd  | pow  | times  | tilde  | question  | pointer  | at  | colon  | implementation  )  | Id
MExpr ::= MId  ( lpar  ( MExpr  ( comma  ( MExpr  )?  )*  )? rpar  | MExpr  |  )  | String  | SignedInteger  | Boolean  | Version  | Null

cr ::= '\r'
lf ::= '\n'
tab ::= '\t'
letter ::= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnoprstuvwxyz\\_"
digit ::= "0123456789"
natDigit ::= digit  '-' "0"
hexDigit ::= digit  '+' "ABCDEFabcdef"
notDigit ::= ANY  '-' digit
char ::= ANY  '-' "'"  '-' '\'  '-' lf
verbatimStringChar ::= ANY  '-' '"'
regularStringChar ::= ANY  '-' '"'  '-' '\'  '-' lf
notNewLine ::= ANY  '-' lf
ws ::= " "  '+' tab  '+' '\u000b'  '+' '\u000c'
at  ::= '@'
id  ::= letter  ( letter  | digit  )*
lid  ::= letter  ( letter  | digit  )* CONTEXT  ( ':'  )
ns  ::= letter  ( letter  | digit  )* CONTEXT  ( "::"  )
integer  ::=  ( digit  ( digit  )*  | digit  ( digit  )* CONTEXT  ( "." notDigit  )  |  ( "0x"  ) hexDigit  ( hexDigit  )*  )
real  ::= digit  ( digit  )*  ( "." digit  ( digit  )*  (  ( "e"  )  ( "+"  | "-"  )? digit  ( digit  )*  )?  |  ( "e"  )  ( "+"  | "-"  )? digit  ( digit  )*  )
string  ::= '"'  ( regularStringChar  | "\'"  | '\"'  | "\\"  | "\0"  | "\a"  | "\b"  | "\f"  | "\n"  | "\r"  | "\t"  | "\v"  | "\x" hexDigit  ( hexDigit  )?  ( hexDigit  )?  ( hexDigit  )?  | "\\u" hexDigit hexDigit hexDigit hexDigit  ( hexDigit hexDigit hexDigit hexDigit  )?  )* '"'  | '@"'  ( verbatimStringChar  | '""'  )* '"'
bitAnd  ::= "&"
assign  ::= "="
comma  ::= ","
dec  ::= "--"
div  ::= "/"
dot  ::= "."
eq  ::= "=="
gt  ::= ">"
ge  ::= ">="
inc  ::= "++"
lbrace  ::= "{"
lbrack  ::= "["
lpar  ::= "("
lt  ::= "<"
le  ::= "<="
minus  ::= "-"
mod  ::= "mod"
ne  ::= "!="
bitOr  ::= "|"
plus  ::= "+"
pow  ::= "^"
rbrace  ::= "}"
rbrack  ::= "]"
rpar  ::= ")"
tilde  ::= "~"
times  ::= "*"
semicolon  ::= ';'
colon  ::= ':'
doublecolon  ::= "::"
question  ::= "?"
pointer  ::= "->"
implementation  ::= "=>"
is  ::= "is"
as  ::= "as"
not  ::= "not"
enabled  ::= "enabled"
disabled  ::= "disabled"
function  ::= "function"
command  ::= "command"
true  ::= "true"
false  ::= "false"
asm  ::= "asm"
ref  ::= "ref"
declare  ::= "declare"
build  ::= "build"
return  ::= "return"
in  ::= "in"
to  ::= "to"
add  ::= "add"
continue  ::= "continue"
break  ::= "break"
or  ::= "or"
and  ::= "and"
xor  ::= "xor"
label  ::= "label"
goto  ::= "goto"
static  ::= "static"
var  ::= "var"
null  ::= "null"
if  ::= "if"
unless  ::= "unless"
else  ::= "else"
new  ::= "new"
do  ::= "do"
does  ::= "does"
while  ::= "while"
until  ::= "until"
for  ::= "for"
foreach  ::= "foreach"
anyId  ::= '`' letter  ( letter  | digit  )*
chklauser commented 3 days ago

Thanks! It's really cool to see some of the more complex rules (e.g., NamespaceDeclaration) through that lens. 😄

image

If I wanted to use this for documentation, I'd probably want to do two things

  1. Inline some of the definitions. For instance the distinction between NsQualifiedId and NsQualifiedIdImpl only exists for their parser side effects. Would probably be fine to manually maintain a list of productions to be "inlined" by your conversion tool.
  2. Split the output by "sub-language", but form the transitive closure. E.g., the byte code assembly language ("asm") doesn't need to be documented together with the rest of the language.

I realize that this response is years too late 😅 but I wanted to express my appreciation for your work regardless.

mingodad commented 3 days ago

I've extended CocoR to output the EBNF here https://github.com/mingodad/CocoR-CSharp/blob/af4b887fa7903edbdbb9d67278dd5855ce717fac/src/ParserGen.cs#L457 also for the Java/C++/Typescript ports:

The Typescript port has an online playground here https://mingodad.github.io/CocoR-Typescript/playground .