Skip to content

Grammar railroad diagram #2

@mingodad

Description

@mingodad

Using a modified byacc (https://github.com/mingodad/lalr-parser-test/tree/main/byacc) that can export an EBNF understood by (IPV4) https://rr.red-dove.com/ui or (IPV6) https://www.bottlecaps.de/rr/ui that generates a nice navigable railroad diagram for the grammar in https://github.com/ncihnegn/miranda/blob/master/rules.y (see the instruction bellow at the top).

//
// 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 url shown above in the 'Edit Grammar' tab
// then click the 'View Diagram' tab.
//
entity ::=
	 /*error
	|*/ script
	| VALUE exp
	| EVAL exp
	| EVAL exp COLONCOLON
	| EVAL exp TO

script ::=
	 /*empty*/
	| defs

exp ::=
	 op
	| e1

op ::=
	 '~'
	| '#'
	| diop

diop ::=
	 '-'
	| diop1

diop1 ::=
	 '+'
	| PLUSPLUS
	| ':'
	| MINUSMINUS
	| VEL
	| '&'
	| relop
	| '*'
	| '/'
	| DIV
	| REM
	| '^'
	| '.'
	| '!'
	| INFIXNAME
	| INFIXCNAME

relop ::=
	 '>'
	| GE
	| eqop
	| NE
	| LE
	| '<'

eqop ::=
	 EQEQ
	| '='

rhs ::=
	 cases WHERE ldefs
	| exp WHERE ldefs
	| exp
	| cases

cases ::=
	 exp ',' if exp
	| exp ',' OTHERWISE
	| cases reindent ELSEQ alt

alt ::=
	 here exp
	| here exp ',' if exp
	| here exp ',' OTHERWISE

if ::=
	 /*empty*/
	| IF

indent ::=
	 /*empty*/

outdent ::=
	 separator

separator ::=
	 OFFSIDE
	| ';'

reindent ::=
	 /*empty*/

liste ::=
	 exp
	| liste ',' exp

e1 ::=
	 '~' e1
	| e1 PLUSPLUS e1
	| e1 ':' e1
	| e1 MINUSMINUS e1
	| e1 VEL e1
	| e1 '&' e1
	| reln
	| e2

es1 ::=
	 '~' e1
	| e1 PLUSPLUS e1
	| e1 PLUSPLUS
	| e1 ':' e1
	| e1 ':'
	| e1 MINUSMINUS e1
	| e1 MINUSMINUS
	| e1 VEL e1
	| e1 VEL
	| e1 '&' e1
	| e1 '&'
	| relsn
	| es2

e2 ::=
	 '-' e2
	| '#' e2
	| e2 '+' e2
	| e2 '-' e2
	| e2 '*' e2
	| e2 '/' e2
	| e2 DIV e2
	| e2 REM e2
	| e2 '^' e2
	| e2 '.' e2
	| e2 '!' e2
	| e3

es2 ::=
	 '-' e2
	| '#' e2
	| e2 '+' e2
	| e2 '+'
	| e2 '-' e2
	| e2 '-'
	| e2 '*' e2
	| e2 '*'
	| e2 '/' e2
	| e2 '/'
	| e2 DIV e2
	| e2 DIV
	| e2 REM e2
	| e2 REM
	| e2 '^' e2
	| e2 '^'
	| e2 '.' e2
	| e2 '.'
	| e2 '!' e2
	| e2 '!'
	| es3

e3 ::=
	 comb INFIXNAME e3
	| comb INFIXCNAME e3
	| comb

es3 ::=
	 comb INFIXNAME e3
	| comb INFIXNAME
	| comb INFIXCNAME e3
	| comb INFIXCNAME
	| comb

comb ::=
	 comb arg
	| arg

reln ::=
	 e2 relop e2
	| reln relop e2

relsn ::=
	 e2 relop e2
	| e2 relop
	| reln relop e2

arg ::=
	 LEX lexrules ENDIR
	| NAME
	| CNAME
	| CONST
	| READVALSY
	| SHOWSYM
	| DOLLAR2
	| '[' ']'
	| '[' exp ']'
	| '[' exp ',' exp ']'
	| '[' exp ',' exp ',' liste ']'
	| '[' exp DOTDOT exp ']'
	| '[' exp DOTDOT ']'
	| '[' exp ',' exp DOTDOT exp ']'
	| '[' exp ',' exp DOTDOT ']'
	| '[' exp '|' qualifiers ']'
	| '[' exp DIAG qualifiers ']'
	| '(' op ')'
	| '(' es1 ')'
	| '(' diop1 e1 ')'
	| '(' ')'
	| '(' exp ',' liste ')'

lexrules ::=
	 lexrules lstart here re indent ARROW exp lpostfix outdent
	| lexdefs

lstart ::=
	 /*empty*/
	| '<' cnames '>'

cnames ::=
	 CNAME
	| cnames CNAME

lpostfix ::=
	 /*empty*/
	| LBEGIN CNAME
	| LBEGIN CONST

lexdefs ::=
	 lexdefs LEXDEF indent '=' re outdent
	| /*empty*/

re ::=
	 re1 '|' re
	| re1

re1 ::=
	 lterm '/' lterm
	| lterm '/'
	| lterm

lterm ::=
	 lfac lterm
	| lfac

lfac ::=
	 lunit '*'
	| lunit '+'
	| lunit '?'
	| lunit

lunit ::=
	 '(' re ')'
	| CONST
	| CHARCLASS
	| ANTICHARCLASS
	| '.'
	| name

name ::=
	 NAME
	| CNAME

qualifiers ::=
	 exp
	| generator
	| qualifiers ';' generator
	| qualifiers ';' exp

generator ::=
	 e1 ',' generator
	| generator1

generator1 ::=
	 e1 LEFTARROW exp
	| e1 LEFTARROW exp ',' exp DOTDOT

defs ::=
	 def
	| defs def

def ::=
	 v act2 indent '=' here rhs outdent
	| spec
	| ABSTYPE here typeforms indent WITH lspecs outdent
	| typeform indent act1 here EQEQ type act2 outdent
	| typeform indent act1 here COLON2EQ construction act2 outdent
	| indent setexp EXPORT parts outdent
	| FREE here '{' specs '}'
	| INCLUDE bindings modifiers outdent

def ::=
	 here BNF names outdent productions ENDIR

setexp ::=
	 here

bindings ::=
	 /*empty*/
	| '{' bindingseq '}'

bindingseq ::=
	 bindingseq binding
	| binding

binding ::=
	 NAME indent '=' exp outdent
	| typeform indent act1 EQEQ type act2 outdent

modifiers ::=
	 /*empty*/
	| negmods

negmods ::=
	 negmods negmod
	| negmod

negmod ::=
	 NAME '/' NAME
	| CNAME '/' CNAME
	| '-' NAME

here ::=
	 /*empty*/

act1 ::=
	 /*empty*/

act2 ::=
	 /*empty*/

ldefs ::=
	 ldef
	| ldefs ldef

ldef ::=
	 spec
	| typeform here EQEQ
	| typeform here COLON2EQ
	| v act2 indent '=' here rhs outdent

vlist ::=
	 v
	| vlist ',' v

v ::=
	 v1
	| v1 ':' v

v1 ::=
	 v1 '+' CONST
	| '-' CONST
	| v2 INFIXNAME v1
	| v2 INFIXCNAME v1
	| v2

v2 ::=
	 v3
	| v2 v3

v3 ::=
	 NAME
	| CNAME
	| CONST
	| '[' ']'
	| '[' vlist ']'
	| '(' ')'
	| '(' v ')'
	| '(' v ',' vlist ')'

type ::=
	 type1
	| type ARROW type

type1 ::=
	 type2 INFIXNAME type1
	| type2

type2 ::=
	 tap
	| argtype

tap ::=
	 NAME argtype
	| tap argtype

argtype ::=
	 NAME
	| typevar
	| '(' typelist ')'
	| '[' type ']'
	| '[' type ',' typel ']'

typelist ::=
	 /*empty*/
	| type
	| type ',' typel

typel ::=
	 type
	| typel ',' type

parts ::=
	 parts NAME
	| parts '-' NAME
	| parts PATHNAME
	| parts '+'
	| NAME
	| '-' NAME
	| PATHNAME
	| '+'

specs ::=
	 specs spec
	| spec

spec ::=
	 typeforms indent here COLONCOLON ttype outdent

lspecs ::=
	 lspecs lspec
	| lspec

lspec ::=
	 namelist indent here COLONCOLON type outdent

namelist ::=
	 NAME ',' namelist
	| NAME

typeforms ::=
	 typeforms ',' typeform act2
	| typeform act2

typeform ::=
	 CNAME typevars
	| NAME typevars
	| typevar INFIXNAME typevar
	| typevar INFIXCNAME typevar

ttype ::=
	 type
	| TYPE

typevar ::=
	 '*'
	| TYPEVAR

typevars ::=
	 /*empty*/
	| typevar typevars

construction ::=
	 constructs

constructs ::=
	 construct
	| constructs '|' construct

construct ::=
	 field here INFIXCNAME field
	| construct1

construct1 ::=
	 '(' construct ')'
	| construct1 field1
	| here CNAME

field ::=
	 type
	| argtype '!'

field1 ::=
	 argtype '!'
	| argtype

names ::=
	 /*empty*/
	| names NAME

productions ::=
	 lspec
	| production
	| productions lspec
	| productions production

production ::=
	 NAME params ':' indent grhs outdent

params ::=
	 /*empty*/

params ::=
	 '(' names ')'

grhs ::=
	 here phrase

phrase ::=
	 error_term
	| phrase1
	| phrase1 '|' error_term

phrase1 ::=
	 term
	| phrase1 '|' here term

term ::=
	 count_factors

term ::=
	 count_factors indent '=' here rhs outdent

error_term ::=
	 ERRORSY

error_term ::=
	 ERRORSY indent '=' here rhs outdent

count_factors ::=
	 EMPTYSY
	| EMPTYSY factors

count_factors ::=
	 factors

factors ::=
	 factor
	| factors factor

factor ::=
	 unit
	| '{' unit '}'
	| '{' unit
	| unit '}'

unit ::=
	 symbol
	| symbol '*'
	| symbol '+'
	| symbol '?'

symbol ::=
	 NAME
	| ENDSY
	| CONST
	| '^'

symbol ::=
	 '[' exp ']'
	| '-'

//Tokens

ABSTYPE ::= "abstype"
//ANTICHARCLASS ::= ANTICHARCLASS
ARROW ::= "->"
BNF ::= "%bnf"
//CHARCLASS ::= CHARCLASS
//CNAME ::= CNAME
COLON2EQ ::= "::="
COLONCOLON ::= "::"
DIAG ::= "//"
DIV ::= "div"
DOLLAR2 ::= "$$"
DOTDOT ::= ".."
ELSEQ ::= ";="
EMPTYSY ::= "empty"
ENDIR ::= "%%"
ENDSY ::= "end"
EQEQ ::= "=="
ERRORSY ::= "error"
//EVAL ::= EVAL
EXPORT ::= "%export"
FREE ::= "%free"
GE ::= ">="
IF ::= "if"
INCLUDE ::= "%include"
LBEGIN ::= "%%begin"
LE ::= "<="
LEFTARROW ::= "<-"
LEX ::= "%lex"
//LEXDEF ::= LEXDEF
MINUSMINUS ::= "--"
NE ::= "~="
//OFFSIDE ::= OFFSIDE
OTHERWISE ::= "otherwise"
//PATHNAME ::= PATHNAME
PLUSPLUS ::= "++"
READVALSY ::= "readvals"
REM ::= "mod"
SHOWSYM ::= "show"
TO ::= "&>"
TYPE ::= "type"
//TYPEVAR ::= TYPEVAR
//VALUE ::= VALUE
VEL ::= "\\/"
WHERE ::= "where"
WITH ::= "with"

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