jsinger67 / parol

LL(k) and LALR(1) parser generator for Rust
https://jsinger67.github.io/
Apache License 2.0
183 stars 18 forks source link

Grammar railroad diagram #347

Closed mingodad closed 5 days ago

mingodad commented 3 months ago

I've just added parol grammar to https://mingodad.github.io/parsertl-playground/playground/ an Yacc/Lex compatible online editor/tester (select Parol parser from Examples then click Parse to see a parser tree for the content in Input source), it can also generate an EBNF understood by https://github.com/GuntherRademacher/rr to generate a nice navigable railroad diagram (see bellow) and a SQL description of the grammar too.

Would be nice if parol could also generate then.

//
// EBNF to be viewd at
//    (IPV6) https://www.bottlecaps.de/rr/ui
//    (IPV4) https://rr.red-dove.com/ui
//
// Copy and paste this at one of the urls shown above in the 'Edit Grammar' tab
// then click the 'View Diagram' tab.
//

Parol::=
      Prolog GrammarDefinition

Prolog::=
      StartDeclaration Declaration_zom ScannerState_zom

ScannerState_zom::=
      /*%empty*/
    | ScannerState_zom ScannerState

Declaration_zom::=
      /*%empty*/
    | Declaration_zom Declaration

StartDeclaration::=
      "%start" Identifier

Declaration::=
      "%title" String
    | "%comment" String
    | "%user_type" Identifier '=' UserTypeName
    | "%grammar_type" RawString
    | ScannerDirectives

ScannerDirectives::=
      "%line_comment" TokenLiteral
    | "%block_comment" TokenLiteral TokenLiteral
    | "%auto_newline_off"
    | "%auto_ws_off"
    | "%on" IdentifierList "%enter" Identifier

GrammarDefinition::=
      "%%" Production Production_zom

Production_zom::=
      /*%empty*/
    | Production_zom Production

DoubleColon::=
      "::"

Production::=
      Identifier ':' Alternations ';'

Alternations::=
      Alternation
    | Alternations '|' Alternation

Alternation::=
      /*%empty*/
    | Alternation Factor

Factor::=
      Group
    | Repeat
    | Optional
    | Symbol

Symbol::=
      NonTerminal
    | SimpleToken
    | TokenWithStates
    | ScannerSwitch

TokenLiteral::=
      String
    | RawString
    | Regex

SimpleToken::=
      TokenLiteral ASTControl_opt

ASTControl_opt::=
      /*%empty*/
    | ASTControl

TokenWithStates::=
      '<' IdentifierList '>' TokenLiteral ASTControl_opt

Group::=
      '(' Alternations ')'

Optional::=
      '[' Alternations ']'

Repeat::=
      '{' Alternations '}'

NonTerminal::=
      Identifier ASTControl_opt

ScannerState::=
      "%scanner" Identifier '{' ScannerDirectives_zom '}'

ScannerDirectives_zom::=
      /*%empty*/
    | ScannerDirectives_zom ScannerDirectives

IdentifierList::=
      Identifier
    | IdentifierList ',' Identifier

ScannerSwitch::=
      "%sc" '(' Identifier_opt ')'
    | "%push" '(' Identifier ')'
    | "%pop" '(' ')'

Identifier_opt::=
      /*%empty*/
    | Identifier

ASTControl::=
      CutOperator
    | UserTypeDeclaration

CutOperator::=
      '^'

UserTypeDeclaration::=
      ':' UserTypeName

UserTypeName::=
      Identifier
    | UserTypeName DoubleColon Identifier
jsinger67 commented 3 months ago

Hello @mingodad, first of all thank you for supporting parol in your project.

I tried a bit with your web site and I only was able to produce EBNF from the parol grammar itself and not from other grammars written in parol's syntax. E.g., if you paste the grammar from https://github.com/jsinger67/parol_grammars/blob/main/grammars/prop_cal.par into the Input source pane it parses it flawlessly and the parse tree is visualized. But when you choose to generate EBNF grammar the content of clippboard always seems to be the same as in the lower left pain. Maybe I handle it wrong.

I like your suggestion to generate railroad diagrams for grammars written in parol's syntax. I'll think about it thoroughly.

mingodad commented 3 months ago

You are right it only generate EBNF, SQL, C++ code for the grammar on the left editor the Input source is just that the input to the grammar on the left.

jsinger67 commented 3 months ago

I see. No problem. I ranked the issue as enhancement. I also will add the 'help wanted' tag. Let's see if anyone can jump in. Otherwise, I'll schedule it for myself because I'm really conviced that this improvement could help users a lot. Thanks again 👍

jsinger67 commented 1 month ago

Maybe an idea how to get around the problem. Create a small tool that reads in parol grammars and outputs an EBNF format, that the tool mentioned above can understand.

jsinger67 commented 5 days ago

Can be solved by an extra application as proposed in my last comment.

To parse parol syntax create a bin crate with

parol new ...

and use parol's parol.par grammar description to create a parser for it. Then write a simple converter to EBNF.

Therefore I close this issue.