agoric-labs / jessica

Jessica - Jessie (secure distributed Javascript) Compiler Architecture
Apache License 2.0
35 stars 9 forks source link

Grammar railroad diagram #61

Open mingodad opened 2 years ago

mingodad commented 2 years ago

Looking through the code I think that adding an option to export the grammar to a format that can be recognized by https://www.bottlecaps.de/rr/ui to generate a navigable railroad diagram (https://en.wikipedia.org/wiki/Syntax_diagram) would make it easier to develop/debug/document jessica.

For example I manually created a grammar compatible with chpeg / cpp-peglib that can parse pegquasi grammars on their playgrounds (https://chrishixon.github.io/chpeg/playground/ , https://yhirose.github.io/cpp-peglib/) :

# Hierarchical syntax

Grammar      <- _Spacing Definition+ _EndOfFile

Definition   <- Identifier LEFTARROW Expression SEMI #&${ACCEPT}

Expression   <- Sequence ( _SLASH Sequence )*

Sequence     <- Prefix* HOLE?

Prefix       <- AND HOLE
              / AND Suffix
              / NOT Suffix
              /     Suffix

Suffix       <- Primary (STARSTAR / PLUSPLUS) Primary
              / Primary (QUESTION
                        / STAR
                        / PLUS)
              / Primary

Primary      <- Super
              / Identifier !LEFTARROW
              / OPEN Expression CLOSE
              / Literal
              / Class
              / DOT
              / BEGIN
              / END

Super        <- 'super.' Identifier

# Lexical syntax

Identifier   <- < IdentStart IdentCont* > _Spacing
IdentStart   <- [a-zA-Z_]
IdentCont    <- IdentStart / [0-9]
Literal      <- ['] < (!['] Char )* > ['] _Spacing
              / ["] < (!["] Char )* > ["] _Spacing
Class        <- '[' < (!']' Range)* > ']' _Spacing
Range        <- Char '-' Char / Char
Char         <- '\\' [abefnrtv'"\[\]\\`$]
              / '\\x' [0-9a-fA-F][0-9a-fA-F]
              / '\\' '-'
              / !'\\' .
LEFTARROW    <- '<-' _Spacing
_SLASH        <- '/' _Spacing              #${_ => SKIP};
SEMI         <- ';' _Spacing
AND          <- '&' _Spacing
NOT          <- '~' _Spacing
QUESTION     <- '?' _Spacing
STAR         <- '*' _Spacing
PLUS         <- '+' _Spacing
OPEN         <- '(' _Spacing
CLOSE        <- ')' _Spacing
DOT          <- '.' _Spacing
#_Spacing {I}     <- (Space / Comment)*        # this line is for chpeg
~_Spacing {I}     <- (Space / Comment)*        # this line is for cpp-peglib
Comment      <- '#' (!EndOfLine .)* EndOfLine
Space        <- ' ' / '\t' / EndOfLine
EndOfLine    <- '\r\n' / '\n' / '\r'
_EndOfFile    <- !.

HOLE_LITERAL <- Literal / [`] < (![`] Char )* > [`] _Spacing
HOLE         <- "${" (!'}' ( HOLE_LITERAL / .))* "}" _Spacing
BEGIN        <- '<' _Spacing
END          <- '>' _Spacing
PLUSPLUS     <- '++' _Spacing
STARSTAR     <- '**' _Spacing

And with a variant of that I could do a basic conversion of jessica to a peg format that can be used at https://www.bottlecaps.de/convert/ to be converted and generate a navigable railroad diagram.

Copy and paste the grammar shown bellow on https://www.bottlecaps.de/convert/ on the Input grammar: textarea and then click the Convert button then click the View Diagram button (that will appear after the conversion) to view the navigable railroad diagram.

 start  <-
     _WS  moduleBody  _EOF 

 LATER  <-
     "~."  ! [0-9] _WS 

 RESERVED_WORD  <-
     "super."  RESERVED_WORD 
    /  (  "insulate"  _WSN  ) 

 primaryExpr  <-
     "super."  primaryExpr 
    /  functionExpr 

 propDef  <-
     methodDef 
    /  "super."  propDef 

 purePropDef  <-
     methodDef 
    /  "super."  purePropDef 

 prePre  <-
     (  PLUSPLUS  /  MINUSMINUS  ) 
    /  "super."  prePre 

 memberPostOp  <-
     "super."  memberPostOp 
    /  LEFT_BRACKET  assignExpr  RIGHT_BRACKET 
    /  LATER  LEFT_BRACKET  assignExpr  RIGHT_BRACKET 
    /  LATER  IDENT_NAME 

 callPostOp  <-
     "super."  callPostOp 
    /  LATER  args 

 postOp  <-
     (  PLUSPLUS  /  MINUSMINUS  )  _WS 

 assignExpr  <-
     arrowFunc 
    /  functionExpr 
    /  lValue  postOp 
    /  lValue  (  EQUALS  /  assignOp  )  assignExpr 
    /  "super."  assignExpr 
    /  primaryExpr 

 pureExpr  <-
     arrowFunc 
    /  "super."  pureExpr 

 lValue  <-
     primaryExpr  LEFT_BRACKET  indexExpr  RIGHT_BRACKET 
    /  primaryExpr  LATER  LEFT_BRACKET  indexExpr  RIGHT_BRACKET 
    /  primaryExpr  DOT  IDENT_NAME 
    /  primaryExpr  LATER  IDENT_NAME 
    /  useVar 

 assignOp  <-
     (  "*="  /  "/="  /  "%="  /  "+="  /  "-="  /  "<<="  /  ">>="  /  ">>>="  /  "&="  /  "^="  /  "|="  /  "**="  )  _WS 

 statement  <-
     block 
    /  IF  LEFT_PAREN  expr  RIGHT_PAREN  arm  ELSE  elseArm 
    /  IF  LEFT_PAREN  expr  RIGHT_PAREN  arm 
    /  breakableStatement 
    /  terminator 
    /  IDENT  COLON  statement 
    /  TRY  block  catcher  finalizer 
    /  TRY  block  catcher 
    /  TRY  block  finalizer 
    /  DEBUGGER  SEMI 
    /  exprStatement 

 arm  <-
     block 

 elseArm  <-
     arm 
    /  IF  LEFT_PAREN  expr  RIGHT_PAREN  arm  ELSE  elseArm 
    /  IF  LEFT_PAREN  expr  RIGHT_PAREN  arm 

 breakableStatement  <-
     FOR  LEFT_PAREN  declOp  forOfBinding  OF  expr  RIGHT_PAREN  arm 
    /  FOR  LEFT_PAREN  declaration  expr  SEMI  expr  RIGHT_PAREN  arm 
    /  WHILE  LEFT_PAREN  expr  RIGHT_PAREN  arm 
    /  SWITCH  LEFT_PAREN  expr  RIGHT_PAREN  LEFT_BRACE  clause  RIGHT_BRACE 

 terminator  <-
     "continue"  _NO_NEWLINE  IDENT  SEMI 
    /  "continue"  _WS  SEMI 
    /  "break"  _NO_NEWLINE  IDENT  SEMI 
    /  "break"  _WS  SEMI 
    /  "return"  _NO_NEWLINE  expr  SEMI 
    /  "return"  _WS  SEMI 
    /  "throw"  _NO_NEWLINE  expr  SEMI 

 block  <-
     LEFT_BRACE  body  RIGHT_BRACE 

 body  <-
     statementItem 

 statementItem  <-
     declaration 
    /  statement 

 declaration  <-
     declOp  binding  (  _COMMA  binding  )  *  SEMI 
    /  functionDecl 

 declOp  <-
     (  "const"  /  "let"  )  _WSN 

 forOfBinding  <-
     bindingPattern 
    /  defVar 

 binding  <-
     bindingPattern  EQUALS  assignExpr 
    /  defVar  EQUALS  assignExpr 
    /  defVar 

 bindingPattern  <-
     LEFT_BRACKET  elementParam  (  _COMMA  elementParam  )  *  RIGHT_BRACKET 
    /  LEFT_BRACE  propParam  (  _COMMA  propParam  )  *  RIGHT_BRACE 

 pattern  <-
     bindingPattern 
    /  defVar 
    /  undefined 
    /  dataLiteral 
    /  HOLE 

 elementParam  <-
     param 

 param  <-
     ELLIPSIS  pattern 
    /  defVar  EQUALS  assignExpr 
    /  pattern 

 propParam  <-
     ELLIPSIS  pattern 
    /  propName  COLON  pattern 
    /  defVar  EQUALS  assignExpr 
    /  defVar 

 exprStatement  <-
     !  cantStartExprStatement  expr  SEMI 

 cantStartExprStatement  <-
     (  "{"  /  "function"  /  "async"  _NO_NEWLINE  "function"  /  "class"  /  "let"  /  "["  )  _WSN 

 terminatedBody  <-
     (  (  !  terminator  statementItem  )  terminator  ) 

 clause  <-
     caseLabel  LEFT_BRACE  terminatedBody  RIGHT_BRACE 

 caseLabel  <-
     CASE  expr  COLON 
    /  DEFAULT  _WS  COLON 

 catcher  <-
     CATCH  LEFT_PAREN  pattern  RIGHT_PAREN  block 

 finalizer  <-
     FINALLY  block 

 functionDecl  <-
     FUNCTION  defVar  LEFT_PAREN  param  (  _COMMA  param  )  *  RIGHT_PAREN  block 

 functionExpr  <-
     FUNCTION  defVar  LEFT_PAREN  param  (  _COMMA  param  )  *  RIGHT_PAREN  block 

 arrowFunc  <-
     arrowParams  _NO_NEWLINE  ARROW  block 
    /  arrowParams  _NO_NEWLINE  ARROW  assignExpr 

 arrowParams  <-
     IDENT 
    /  LEFT_PAREN  param  (  _COMMA  param  )  *  RIGHT_PAREN 

 methodDef  <-
     method 
    /  GET  propName  LEFT_PAREN  RIGHT_PAREN  block 
    /  SET  propName  LEFT_PAREN  param  RIGHT_PAREN  block 

 method  <-
     propName  LEFT_PAREN  param  (  _COMMA  param  )  *  RIGHT_PAREN  block 

 moduleBody  <-
     moduleItem 

 moduleItem  <-
     SEMI 
    /  importDecl 
    /  exportDecl 
    /  moduleDeclaration 

 useImport  <-
     IDENT 

 defImport  <-
     IDENT 

 moduleDeclaration  <-
     "const"  _WSN  moduleBinding  (  _COMMA  moduleBinding  )  *  SEMI 

 hardenedExpr  <-
     dataLiteral 
    /  undefined 
    /  "harden"  _WS  LEFT_PAREN  (  pureExpr  /  useImport  )  RIGHT_PAREN 
    /  useVar 

 moduleBinding  <-
     bindingPattern  EQUALS  hardenedExpr 
    /  defVar  EQUALS  hardenedExpr 
    /  defVar 

 importClause  <-
     STAR  AS  defImport 
    /  namedImports 
    /  defImport  _COMMA  STAR  AS  defImport 
    /  defImport  _COMMA  namedImports 
    /  defImport 

 safeImportClause  <-
     safeNamedImports 

 importSpecifier  <-
     IDENT_NAME  AS  defImport 
    /  defImport 

 safeImportSpecifier  <-
     IDENT_NAME  AS  defVar 
    /  defVar 

 namedImports  <-
     LEFT_BRACE  importSpecifier  (  _COMMA  importSpecifier  )  *  _COMMA  RIGHT_BRACE 

 safeNamedImports  <-
     LEFT_BRACE  safeImportSpecifier  (  _COMMA  safeImportSpecifier  )  *  _COMMA  RIGHT_BRACE 

 safeModule  <-
     STRING 

 importDecl  <-
     IMPORT  importClause  FROM  STRING  SEMI 
    /  IMPORT  safeImportClause  FROM  safeModule  SEMI 

 exportDecl  <-
     EXPORT  DEFAULT  exportableExpr  SEMI 
    /  EXPORT  moduleDeclaration 

 exportableExpr  <-
     hardenedExpr 

 ARROW  <-
     "=>"  _WS 

 AS  <-
     "as"  _WSN 

 DEBUGGER  <-
     "debugger"  _WSN 

 PLUSPLUS  <-
     "++"  _WSN 

 MINUSMINUS  <-
     "--"  _WSN 

 CASE  <-
     "case"  _WSN 

 IF  <-
     "if"  _WSN 

 ELSE  <-
     "else"  _WSN 

 FOR  <-
     "for"  _WSN 

 OF  <-
     "of"  _WSN 

 WHILE  <-
     "while"  _WSN 

 BREAK  <-
     "break"  _WSN 

 CONTINUE  <-
     "continue"  _WSN 

 SWITCH  <-
     "switch"  _WSN 

 TRY  <-
     "try"  _WSN 

 CATCH  <-
     "catch"  _WSN 

 FINALLY  <-
     "finally"  _WSN 

 GET  <-
     "get"  _WSN 

 SET  <-
     "set"  _WSN 

 IMPORT  <-
     "import"  _WSN 

 EXPORT  <-
     "export"  _WSN 

 FROM  <-
     "from"  _WSN 

 FUNCTION  <-
     "function"  _WSN 

 DEFAULT  <-
     "default"  _WSN 

 EQUALS  <-
     "="  _WS 

 SEMI  <-
     ";"  _WS 

 STAR  <-
     "*"  _WS 
erights commented 2 years ago

@mingodad wow, this looks like great work! What do you think we should add to this repository? Would you be interesting in submitting a PR? I would happily review, thanks!

mingodad commented 2 years ago

Why not add the capability to export the grammar like I did manually directly in the pegquasi itself ?

erights commented 2 years ago

Hi @michaelfig I added you to the assignees along with me. Looks like fun! Let's discuss sometime. No rush.