Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grammar railroad diagram #16

Open
mingodad opened this issue Jan 17, 2023 · 2 comments
Open

Grammar railroad diagram #16

mingodad opened this issue Jan 17, 2023 · 2 comments

Comments

@mingodad
Copy link

After extend btyacc (see diff bellow) to output an EBNF understood by https://www.bottlecaps.de/rr/ui and manually add the tokens from parser.l we can have a nice navigable railroad diagram.

Copy and paste the EBNF shown bellow on https://www.bottlecaps.de/rr/ui on the tab Edit Grammar the click on the tab View Diagram to see/download a navigable railroad diagram.

//EBNF to create railroad diagram


progunit ::= optstmtlist

optstmtlist ::=
            | stmtlist

stmtlist ::= stmt
         | stmtlist stmt
         | optstmtlist changeprotlevel

stmt ::= vardeclstmt
     | vardeclliststmt
     | enumdefnstmt
     | enumfwddecl
     | typedefnamestmt
     | typedefliststmt
     | classdefnstmt
     | namespacedefn
     | fwddecl
     | doccomment
     | exprstmt
     | ifblock
     | whileblock
     | dowhileblock
     | forblock
     | forrangeblock
     | funcpointerdecl
     | funcdeclstmt
     | funcdefn
     | ctordeclstmt
     | ctordefn
     | dtordeclstmt
     | dtordefn
     | typeconverterstmt
     | externcblock
     | funcptrtypedef
     | preprocessor
     | block
     | switchstmt
     | tryblock
     | usingdecl
     | usingnamespacedecl
     | namespacealias
     | macrocall
     | macrocall ';'
     | apidecortokensq macrocall
     | ';'
     | asmblock
     | blob
     | label

label ::= name ':'

preprocessor ::= define
             | undef
             | include
             | import
             | hashif
             | hasherror
             | hashwarning
             | pragma

asmblock ::= tknAsm


macrocall ::= tknMacro


macrocall ::= macrocall '(' ')'


macrocall ::= macrocall '(' expr ')'

switchstmt ::= tknSwitch '(' expr ')' '{' caselist '}'

caselist ::=
         | caselist tknCase expr ':' optstmtlist
         | caselist tknDefault ':' optstmtlist
         | doccommentstr caselist
         | caselist doccommentstr

block ::= '{' optstmtlist '}'
      | doccomment block

ifblock ::= tknIf '(' expr ')' stmt
        | tknIf '(' varinit ')' stmt
        | ifblock tknElse stmt

whileblock ::= tknWhile '(' expr ')' stmt
           | tknWhile '(' varinit ')' stmt

dowhileblock ::= tknDo stmt tknWhile '(' expr ')'

forblock ::= tknFor '(' optexpr ';' optexpr ';' optexpr ')' stmt
         | tknFor '(' varinit ';' optexpr ';' optexpr ')' stmt
         | tknFor '(' vardecllist ';' optexpr ';' optexpr ')' stmt

forrangeblock ::= tknFor '(' vardecl ':' expr ')' stmt

tryblock ::= tknTry block catchblock
         | tryblock catchblock

catchblock ::= tknCatch '(' vartype optname ')' block

optexpr ::=
        | expr
        | exprlist

define ::= tknPreProHash tknDefine name name
       | tknPreProHash tknDefine name
       | tknPreProHash tknDefine name tknNumber
       | tknPreProHash tknDefine name tknStrLit
       | tknPreProHash tknDefine name tknCharLit
       | tknPreProHash tknDefine name tknPreProDef

undef ::= tknPreProHash tknUndef name

include ::= tknPreProHash tknInclude tknStrLit
        | tknPreProHash tknInclude tknStdHdrInclude

import ::= tknPreProHash tknImport tknStrLit
       | tknPreProHash tknImport tknStdHdrInclude

hashif ::= tknPreProHash tknIf tknPreProDef
       | tknPreProHash tknIfDef name
       | tknPreProHash tknIfNDef name
       | tknPreProHash tknIfNDef tknApiDecor
       | tknPreProHash tknElse
       | tknPreProHash tknElIf tknPreProDef
       | tknPreProHash tknEndIf

hasherror ::= tknPreProHash tknHashError
          | tknPreProHash tknHashError strlit

hashwarning ::= tknPreProHash tknHashWarning
            | tknPreProHash tknHashWarning strlit

pragma ::= tknPreProHash tknPragma tknPreProDef

doccomment ::= doccommentstr

doccommentstr ::= tknFreeStandingBlockComment
              | tknFreeStandingLineComment
              | doccommentstr tknFreeStandingBlockComment
              | doccommentstr tknFreeStandingLineComment


identifier ::= name


identifier ::= identifier tknScopeResOp identifier


identifier ::= id


identifier ::= templidentifier


identifier ::= tknOverride


identifier ::= identifier tknEllipsis


identifier ::= macrocall


identifier ::= templqualifiedid

numbertype ::= tknInteger
           | tknFloat
           | tknDouble
           | tknChar
           | tknNumSignSpec
           | tknNumSignSpec numbertype

typeidentifier ::= identifier
               | tknScopeResOp identifier
               | typeidentifier tknScopeResOp typeidentifier
               | numbertype
               | tknAuto
               | tknVoid
               | tknEnum identifier
               | tknTypename identifier
               | tknEllipsis
               | tknTypename tknEllipsis
               | tknClass tknEllipsis
               | typeidentifier tknEllipsis
               | tknDecltype '(' expr ')'


templidentifier ::= identifier tknLT templatearglist tknGT


templidentifier ::= identifier tknLT expr tknNotEq expr tknGT


templidentifier ::= identifier tknLT templatearglist ',' expr tknNotEq expr tknGT


templqualifiedid ::= tknTemplate templidentifier


name ::= tknName


id ::= tknID

optname ::=
        | name

optidentifier ::=
              | identifier

enumitem ::= name
         | name '=' expr
         | doccomment
         | preprocessor
         | macrocall
         | blob

blob ::= tknBlob

enumitemlist ::=
             | enumitemlist enumitem
             | enumitemlist ',' enumitem
             | enumitemlist ','

enumdefn ::= tknEnum optname '{' enumitemlist '}'
         | tknEnum optapidecor name ':' typeidentifier '{' enumitemlist '}'
         | tknEnum ':' typeidentifier '{' enumitemlist '}'
         | tknEnum optapidecor name '{' enumitemlist '}'
         | tknEnum tknClass optapidecor name ':' typeidentifier '{' enumitemlist '}'
         | tknEnum tknClass optapidecor name '{' enumitemlist '}'
         | tknTypedef tknEnum optapidecor optname '{' enumitemlist '}' name

enumdefnstmt ::= enumdefn ';'

enumfwddecl ::= tknEnum name ':' typeidentifier ';'
            | tknEnum tknClass name ':' typeidentifier ';'
            | tknEnum tknClass name ';'

funcptrtypedef ::= tknTypedef functionpointer ';'

typedefnamestmt ::= typedefname ';'

typedefliststmt ::= typedeflist ';'

typedeflist ::= tknTypedef vardecllist

typedefname ::= tknTypedef vardecl

usingdecl ::= tknUsing name '=' vartype ';'
          | tknUsing name '=' functionptrtype ';'
          | tknUsing name '=' funcobj ';'
          | tknUsing name '=' classdefn ';'
          | templatespecifier usingdecl
          | tknUsing identifier ';'

namespacealias ::= tknNamespace name '=' identifier ';'

usingnamespacedecl ::= tknUsing tknNamespace identifier ';'

vardeclliststmt ::= vardecllist ';'
                | exptype vardecllist ';'

vardeclstmt ::= vardecl ';'
            | varinit ';'
            | apidecor vardeclstmt
            | exptype vardeclstmt
            | varattrib vardeclstmt

vardecllist ::= optfunctype varinit ',' opttypemodifier name optvarassign
            | optfunctype vardecl ',' opttypemodifier name optvarassign
            | optfunctype vardecl ',' opttypemodifier name '[' expr ']'
            | optfunctype vardecl ',' opttypemodifier name ':' expr
            | vardecllist ',' opttypemodifier name optvarassign
            | vardecllist ',' opttypemodifier name optvarassign ':' expr

varinit ::= vardecl '(' typeidentifier '*' name
        | vardecl '(' typeidentifier '*' '*' name
        | vardecl '(' typeidentifier '*' '&' name
        | vardecl '(' typeidentifier '&' name
        | vardecl '(' typeidentifier tknAnd name
        | vardecl '(' typeidentifier ')'
        | vardecl '(' ')'
        | vardecl varassign
        | tknConstExpr varinit

varassign ::= '=' expr
          | '(' exprorlist ')'
          | '{' funcargs '}'

optvarassign ::=
             | varassign

vardecl ::= vartype varidentifier
        | vartype apidecor varidentifier
        | functionpointer
        | vardecl '[' expr ']'
        | vardecl '[' ']'
        | vardecl ':' expr
        | templatespecifier vardecl
        | varattrib vardecl

vartype ::= attribspecifiers typeidentifier opttypemodifier
        | typeidentifier opttypemodifier
        | tknClass identifier opttypemodifier
        | tknClass optapidecor identifier opttypemodifier
        | tknStruct optapidecor identifier opttypemodifier
        | tknUnion identifier opttypemodifier
        | functionptrtype
        | classdefn
        | classdefn typemodifier
        | enumdefn
        | enumdefn typemodifier
        | varattrib vartype
        | vartype tknEllipsis
        | typeidentifier typeidentifier tknScopeResOp typemodifier

varidentifier ::= identifier
              | tknFinal
              | '(' '&' name ')'
              | '(' '*' name ')'
              | '(' '*' '*' name ')'

opttypemodifier ::=
                | typemodifier
                | doccomment opttypemodifier

typemodifier ::= tknConst
             | '*'
             | '&'
             | tknAnd
             | typemodifier tknConst
             | typemodifier '*'
             | typemodifier '&'
             | typemodifier tknAnd

exptype ::= tknStatic
        | tknExtern
        | tknExternC

varattrib ::= tknConst
          | tknVolatile
          | tknMutable
          | tknConstExpr

typeconverter ::= tknOperator vartype '(' optvoid ')'
              | identifier tknScopeResOp tknOperator vartype '(' optvoid ')'
              | functype typeconverter
              | typeconverter tknConst
              | apidecor typeconverter
              | templatespecifier typeconverter

typeconverterstmt ::= typeconverter ';'
                  | typeconverter block

funcdeclstmt ::= funcdecl ';'

funcdefn ::= funcdecl block

lambda ::= '[' lambdacapture ']' lambdaparams block
       | '[' lambdacapture ']' lambdaparams tknArrow vartype block

lambdaparams ::=
             | '(' paramlist ')'

funcptrortype ::= functype vartype '(' optapidecor identifier tknScopeResOp '*' optname ')' '(' paramlist ')'
              | vartype '(' optapidecor identifier tknScopeResOp '*' optname ')' '(' paramlist ')'
              | functype vartype '(' optapidecor '*' optname ')' '(' paramlist ')'
              | vartype '(' optapidecor '*' optname ')' '(' paramlist ')'
              | vartype '(' '*' apidecor optname ')' '(' paramlist ')'
              | apidecor funcptrortype
              | funcptrortype optfuncattrib

functionpointer ::= funcptrortype

functionptrtype ::= funcptrortype

funcobj ::= vartype optapidecor '(' paramlist ')'

funcpointerdecl ::= functionpointer ';'

funcdecldata ::= funcname '(' paramlist ')'
             | funcname '(' paramlist ')' optfuncattrib

funcdecl ::= vartype apidecor funcdecldata
         | vartype funcdecldata
         | vartype tknConstExpr funcdecldata
         | tknAuto funcdecldata tknArrow vartype
         | tknAuto tknConstExpr funcdecldata tknArrow vartype
         | tknConstExpr funcdecl
         | apidecor funcdecl
         | templatespecifier funcdecl
         | functype funcdecl
         | funcdecl '=' tknDelete
         | funcdecl '=' tknDefault
         | funcdecl functhrowspec

funcobjstr ::= typeidentifier optapidecor '(' paramlist ')'

funcname ::= operfuncname
         | typeidentifier
         | tknScopeResOp operfuncname
         | tknFinal

rshift ::= tknGT tknGT

operfuncname ::= tknOperator '+'
             | tknOperator '-'
             | tknOperator '*'
             | tknOperator '/'
             | tknOperator '%'
             | tknOperator '^'
             | tknOperator '&'
             | tknOperator '|'
             | tknOperator '~'
             | tknOperator '!'
             | tknOperator '='
             | tknOperator tknLT
             | tknOperator tknGT
             | tknOperator tknPlusEq
             | tknOperator tknMinusEq
             | tknOperator tknMulEq
             | tknOperator tknDivEq
             | tknOperator tknPerEq
             | tknOperator tknXorEq
             | tknOperator tknAndEq
             | tknOperator tknOrEq
             | tknOperator tknLShift
             | tknOperator tknRShift
             | tknOperator tknLShiftEq
             | tknOperator tknRShiftEq
             | tknOperator tknCmpEq
             | tknOperator tknNotEq
             | tknOperator tknLessEq
             | tknOperator tknGreaterEq
             | tknOperator tkn3WayCmp
             | tknOperator tknAnd
             | tknOperator tknOr
             | tknOperator tknInc
             | tknOperator tknDec
             | tknOperator ','
             | tknOperator tknArrow
             | tknOperator tknArrowStar
             | tknOperator '(' ')'
             | tknOperator '[' ']'
             | tknOperator tknNew
             | tknOperator tknNew '[' ']'
             | tknOperator tknDelete
             | tknOperator tknDelete '[' ']'
             | tknOperator typeidentifier
             | tknOperator typeidentifier '*'
             | identifier tknScopeResOp operfuncname
             | tknOperator tknStrLit name
             | operfuncname tknLT templatearglist tknGT

paramlist ::=
          | param
          | paramlist ',' param

param ::= varinit
      | vartype '=' expr
      | vardecl
      | vartype
      | funcptrortype
      | doccomment param
      | vartype '[' expr ']'
      | vartype '[' ']'


templatearg ::=


templatearg ::= vartype


templatearg ::= funcobjstr


templatearg ::= expr


templatearglist ::= templatearg


templatearglist ::= templatearglist ',' templatearg


templatearglist ::= templatearglist ',' doccomment templatearg

functype ::= exptype
         | tknInline
         | tknVirtual
         | tknExplicit
         | tknFriend
         | tknConstExpr

optfunctype ::=
            | functype

optfuncattrib ::= tknConst
              | tknOverride
              | tknFinal
              | tknNoExcept
              | '=' tknNumber
              | optfuncattrib tknConst
              | optfuncattrib tknOverride
              | optfuncattrib tknFinal
              | optfuncattrib tknNoExcept
              | optfuncattrib '=' tknNumber
              | tknMacro

optfuncthrowspec ::=
                 | functhrowspec

functhrowspec ::= tknThrow '(' identifierlist ')'

identifierlist ::=
               | identifier
               | identifierlist ',' identifier

ctordeclstmt ::= ctordecl ';'

ctordefn ::= ctordecl meminitlist block


ctordefn ::= name tknScopeResOp name '(' paramlist ')' optfuncthrowspec meminitlist block


ctordefn ::= identifier tknScopeResOp name tknScopeResOp name '(' paramlist ')' optfuncthrowspec meminitlist block


ctordefn ::= name tknLT templatearglist tknGT tknScopeResOp name '(' paramlist ')' optfuncthrowspec meminitlist block
         | functype ctordefn
         | templatespecifier ctordefn

ctordecl ::= identifier '(' paramlist ')'
         | functype ctordecl
         | templatespecifier ctordecl
         | ctordecl '=' tknDelete
         | ctordecl '=' tknDefault
         | ctordecl functhrowspec
         | ctordecl tknNoExcept
         | apidecor ctordecl

meminitlist ::=
            | ':' meminit
            | ':' blob
            | meminitlist ',' meminit

meminit ::= identifier '(' exprorlist ')'
        | identifier '(' ')'
        | identifier '{' exprorlist '}'
        | identifier '{' '}'

dtordeclstmt ::= dtordecl ';'

dtordefn ::= dtordecl block


dtordefn ::= name tknScopeResOp '~' name '(' ')' block


dtordefn ::= identifier tknScopeResOp name tknScopeResOp '~' name '(' ')' block


dtordefn ::= name tknLT templatearglist tknGT tknScopeResOp '~' name '(' ')' block
         | templatespecifier dtordefn
         | functype dtordefn

dtordecl ::= '~' name '(' optvoid ')'
         | apidecor dtordecl
         | functype dtordecl
         | dtordecl optfuncattrib
         | dtordecl '=' tknNumber
         | dtordecl '=' tknDelete
         | dtordecl '=' tknDefault
         | dtordecl functhrowspec

optvoid ::=
        | tknVoid

optcomment ::=
           | doccomment

classdefnstmt ::= classdefn ';'

attribspecifier ::= '[' '[' expr ']' ']'

optattribspecifiers ::=
                    | attribspecifiers

attribspecifiers ::= attribspecifier
                 | attribspecifiers attribspecifier


classdefn ::= classspecifier optapidecor optattribspecifiers identifier optfinal optinheritlist optcomment '{' optstmtlist '}'


classdefn ::= classspecifier optattribspecifiers optinheritlist optcomment '{' optstmtlist '}'
          | templatespecifier classdefn


namespacedefn ::= tknNamespace optidentifier '{' optstmtlist '}'

optfinal ::=
         | tknFinal

optinheritlist ::=
               | ':' protlevel optinherittype typeidentifier
               | optinheritlist ',' protlevel optinherittype typeidentifier
               | ':' optinherittype protlevel typeidentifier
               | optinheritlist ',' optinherittype protlevel typeidentifier

protlevel ::=
          | tknPublic
          | tknProtected
          | tknPrivate

optinherittype ::=
               | tknVirtual

fwddecl ::= classspecifier typeidentifier ';'
        | classspecifier optapidecor identifier ';'
        | templatespecifier fwddecl
        | tknFriend typeidentifier ';'
        | tknFriend fwddecl

classspecifier ::= tknClass
               | tknStruct
               | tknUnion


templatespecifier ::= tknTemplate tknLT templateparamlist tknGT

templateparamlist ::=
                  | templateparam
                  | templateparamlist ',' templateparam

templateparam ::= tknTypename optname
              | tknTypename optname '=' vartype
              | tknClass optname
              | tknClass optname '=' vartype
              | vartype name
              | vartype name '=' expr
              | functionpointer
              | functionpointer '=' expr
              | vartype
              | vartype '=' expr
              | tknTypename name ','
              | tknTypename name '='
              | tknTypename name tknGT
              | tknClass name ','
              | tknClass name tknGT

optapidecor ::=
            | apidecor

apidecor ::= apidecortokensq
         | apidecortokensq '(' name ')'
         | apidecortokensq '(' tknNumber ')'
         | apidecortokensq '(' strlit ')'

apidecortokensq ::= tknApiDecor
                | apidecortokensq tknApiDecor
                | tknApiDecor '(' strlit ')'

changeprotlevel ::= tknPublic ':'
                | tknProtected ':'
                | tknPrivate ':'

externcblock ::= tknExternC block

strlit ::= tknStrLit
       | strlit tknStrLit

expr ::= strlit
     | tknCharLit
     | tknNumber
     | '+' tknNumber
     | identifier
     | '{' exprlist '}'
     | '{' exprlist ',' '}'
     | '{' exprorlist '}'
     | '{' exprorlist ',' '}'
     | '{' '}'
     | '-' expr
     | '~' expr
     | '!' expr
     | '*' expr
     | '&' expr
     | '&' operfuncname
     | tknInc expr
     | expr tknInc
     | tknDec expr
     | expr tknDec
     | expr '+' expr
     | expr '-' expr
     | expr '*' expr
     | expr '/' expr
     | expr '%' expr
     | expr '&' expr
     | expr '|' expr
     | expr '^' expr
     | expr '=' expr
     | expr tknLT expr
     | expr tknGT expr
     | expr '?' expr ':' expr
     | expr tknPlusEq expr
     | expr tknMinusEq expr
     | expr tknMulEq expr
     | expr tknDivEq expr
     | expr tknPerEq expr
     | expr tknXorEq expr
     | expr tknAndEq expr
     | expr tknOrEq expr
     | expr tknLShift expr
     | expr rshift expr
     | expr tknLShiftEq expr
     | expr tknRShiftEq expr
     | expr tknCmpEq expr
     | expr tknNotEq expr
     | expr tknLessEq expr
     | expr tknGreaterEq expr
     | expr tkn3WayCmp expr
     | expr tknAnd expr
     | expr tknOr expr
     | expr '.' funcname
     | expr '.' '*' funcname
     | expr tknArrow funcname
     | expr tknArrowStar funcname
     | expr '.' '~' funcname
     | expr tknArrow '~' funcname
     | expr '[' expr ']'
     | expr '[' ']'
     | expr '(' funcargs ')'
     | funcname '(' funcargs ')'
     | expr tknArrow '~' identifier '(' ')'
     | identifier '{' funcargs '}'
     | '(' vartype ')' expr
     | tknConstCast tknLT vartype tknGT '(' expr ')'
     | tknStaticCast tknLT vartype tknGT '(' expr ')'
     | tknDynamicCast tknLT vartype tknGT '(' expr ')'
     | tknReinterpretCast tknLT vartype tknGT '(' expr ')'
     | '(' exprorlist ')'
     | tknNew typeidentifier opttypemodifier
     | tknNew expr
     | tknNew '(' expr ')' expr
     | tknScopeResOp tknNew '(' expr ')' expr
     | tknDelete expr
     | tknDelete '[' ']' expr
     | tknReturn exprorlist
     | tknReturn
     | tknThrow expr
     | tknThrow
     | tknSizeOf '(' vartype ')'
     | tknSizeOf '(' expr ')'
     | tknSizeOf tknEllipsis '(' vartype ')'
     | tknSizeOf tknEllipsis '(' expr ')'
     | expr tknEllipsis
     | lambda
     | tknGoto name
     | tknNumber name
     | '[' expr expr ']'
     | '[' expr objcarglist ']'

objcarg ::= name ':' expr

objcarglist ::= objcarg
            | objcarglist objcarg

exprlist ::= expr ',' expr
         | exprlist ',' expr
         | doccommentstr exprlist

exprorlist ::= expr
           | exprlist
           | doccommentstr exprorlist

funcargs ::=
         | exprorlist

captureallbyref ::= '&'

captureallbyval ::= '='

lambdacapture ::= funcargs
              | captureallbyref
              | captureallbyval

exprstmt ::= expr ';'

// Tokens

tknScopeResOp ::= "::"
tknConst ::= "const"
tknConstExpr ::= "constexpr"
tknStatic ::= "static"
tknInline ::= "inline"
tknVirtual ::= "virtual"
tknOverride ::= "override"
tknFinal ::= "final"
tknNoExcept ::= "noexcept"
tknExtern ::= "extern"
tknExplicit ::= "explicit"
tknFriend ::= "friend"
tknExternC ::= "extern" '"C"'
tknVolatile ::= "volatile"
tknMutable ::= "mutable"
tknNew ::= "new"
tknDelete ::= "delete"
tknDefault ::= "default"
tknReturn ::= "return"
tknIf ::= "if"
tknElse ::= "else"
tknFor ::= "for"
tknDo ::= "do"
tknWhile ::= "while"
tknSwitch ::= "switch"
tknCase ::= "case"
tknConstCast ::= "const_cast"
tknStaticCast ::= "static_cast"
tknDynamicCast ::= "dynamic_cast"
tknReinterpretCast ::= "reinterpret_cast"
tknTry ::= "try"
tknCatch ::= "catch"
tknThrow ::= "throw"
tknSizeOf ::= "sizeof"
tknOperator ::= "operator"
tknVoid ::= "void"
tknPlusEq ::= "+="
tknMinusEq ::= "-="
tknMulEq ::= "*="
tknDivEq ::= "/="
tknPerEq ::= "%="
tknXorEq ::= "^="
tknAndEq ::= "&="
tknOrEq ::= "|="
tknLShift ::= "<<"
tknLShiftEq ::= "<<="
tknLT ::= "<"
tknRShift ::= ">>"
tknGT ::= ">"
tknRShiftEq ::= ">>="
tknCmpEq ::= "=="
tknNotEq ::= "!="
tknLessEq ::= "<="
tknGreaterEq ::= ">="
tkn3WayCmp ::= "<=>"
tknAnd ::= "&&"
tknOr ::= "||"
tknInc ::= "++"
tknDec ::= "--"
tknArrow ::= "->"
tknArrowStar ::= "->*"

tknAsm ::= "asm"
tknGoto ::= "goto"
tknNumSignSpec ::= "signed" | "unsigned"
tknInteger ::= "long" "long" "int" | "long" "long" | "long" "int" | "long" | "int" | "short" "int"| "short"
tknInteger ::= "__int8" | "__int16" | "__int32" | "__int64" | "__int128"
tknChar ::= "char"
tknDouble ::= "long" "double" | "double"
tknFloat ::= "long" "float" | "float"
tknAuto ::= "auto"
tknTypedef ::= "typedef"
tknUsing ::= using
tknClass ::= "class"
tknNamespace ::= "namespace"
tknStruct ::= "struct"
tknUnion ::= "union"
tknEnum ::= "enum" ("class"? ID? (":"* ID)? "{")?
tknPublic ::= "public" ":"?
tknProtected ::= "protected"":"?
tknPrivate ::= "private" ":"?
tknTemplate ::= "template"
tknTypename ::= "typename"
tknDecltype ::= "decltype"

tknPreProHash ::= '#'
tknDefine ::= "define"
tknUndef ::= "undef"
tknInclude ::= "include"
tknHashErrror ::= "error"
tknPragma ::= "pragma"
tknImport ::= "import"
tknElif ::= "elif"
tknIfdef ::= "ifdef"
tknIfndef ::= "ifndef"
tknEndif ::= "endif"
tknHashWarning ::= "warning"

Patch to add EBNF output to btyacc:

diff --git a/third_party/btyacc_tp/btyacc/defs.h b/third_party/btyacc_tp/btyacc/defs.h
index 2b738773..9009e6ae 100644
--- a/third_party/btyacc_tp/btyacc/defs.h
+++ b/third_party/btyacc_tp/btyacc/defs.h
@@ -69,6 +69,7 @@ typedef int Yshort;
 #define CODE_SUFFIX     ".code.c"
 #endif /* MSDOS */
 #define VERBOSE_SUFFIX  ".output"
+#define EBNF_SUFFIX     ".ebnf"
 
 /* keyword codes */
 
@@ -254,6 +255,7 @@ extern char rflag;
 extern char tflag;
 extern char vflag;
 extern char include_defines;
+extern char ebnfflag;
 
 extern char *myname;
 extern char *symbol_prefix;
@@ -278,6 +280,7 @@ extern FILE *output_file;
 extern FILE *text_file;
 extern FILE *union_file;
 extern FILE *verbose_file;
+extern FILE *ebnf_file;
 
 extern int nitems;
 extern int nrules;
@@ -534,6 +537,7 @@ void check_symbols(void);
 void pack_symbols(void);
 void pack_grammar(void);
 void print_grammar(void);
+void print_grammar_ebnf(void);
 void reader(void);
 
 /* readskel.c */
diff --git a/third_party/btyacc_tp/btyacc/main.c b/third_party/btyacc_tp/btyacc/main.c
index 7ab280b4..9062fecd 100644
--- a/third_party/btyacc_tp/btyacc/main.c
+++ b/third_party/btyacc_tp/btyacc/main.c
@@ -8,6 +8,7 @@ char lflag;
 char rflag;
 char tflag;
 char vflag;
+char ebnfflag;
 int Eflag = 0;
 
 char *symbol_prefix = "yy";
@@ -33,6 +34,7 @@ char *output_file_name;
 char *text_file_name;
 char *union_file_name;
 char *verbose_file_name;
+char *ebnf_file_name;
 
 FILE *action_file;	/*  a temp file, used to save actions associated    */
 			/*  with rules until the parser is written	    */
@@ -45,6 +47,7 @@ FILE *union_file;	/*  a temp file, used to save the union		    */
 			/*  definition until all symbol have been	    */
 			/*  defined					    */
 FILE *verbose_file;	/*  y.output					    */
+FILE *ebnf_file;	/*  y.ebnf					    */
 
 int nitems;
 int nrules;
@@ -101,7 +104,7 @@ void set_signals()
 
 void usage()
 {
-    fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-S skeleton file] "
+    fprintf(stderr, "usage: %s [-delrtv] [-b file_prefix] [-S skeleton file] "
 		    "[-p symbol_prefix] filename\n", myname);
     exit(1);
 }
@@ -167,6 +170,10 @@ void getargs(int argc, char **argv)
 	    }
 	    continue;
 
+	case 'e':
+	    ebnfflag = 1;
+	    break;
+
 	case 'E':
 	    Eflag = 1;
 	    break;
@@ -215,6 +222,10 @@ void getargs(int argc, char **argv)
 		dflag = 1;
 		break;
 
+	    case 'e':
+		ebnfflag = 1;
+		break;
+
 	    case 'l':
 		lflag = 1;
 		break;
@@ -375,6 +386,15 @@ void create_file_names()
 	strcpy(defines_file_name + len, DEFINES_SUFFIX);
     }
 
+    if (ebnfflag)
+    {
+	ebnf_file_name = MALLOC(len + 8);
+	if (ebnf_file_name == 0)
+	    no_space();
+	strcpy(ebnf_file_name, file_prefix);
+	strcpy(ebnf_file_name + len, EBNF_SUFFIX);
+    }
+
     if (vflag)
     {
 	verbose_file_name = MALLOC(len + 8);
@@ -405,6 +425,13 @@ void open_files()
 	    open_error(verbose_file_name);
     }
 
+    if (ebnfflag)
+    {
+	ebnf_file = fopen(ebnf_file_name, "w");
+	if (ebnf_file == 0)
+	    open_error(ebnf_file_name);
+    }
+
     if (dflag)
     {
 	defines_file = fopen(defines_file_name, "w");
diff --git a/third_party/btyacc_tp/btyacc/reader.c b/third_party/btyacc_tp/btyacc/reader.c
index b87a617b..71c4750d 100644
--- a/third_party/btyacc_tp/btyacc/reader.c
+++ b/third_party/btyacc_tp/btyacc/reader.c
@@ -2010,6 +2010,39 @@ void print_grammar()
 	putc('\n', f); }
 }
 
+void print_grammar_ebnf()
+{
+    register int i, j, k, skip_rule;
+    int spacing = 0;
+    register FILE *f = ebnf_file;
+    const char *name;
+
+    if (!ebnfflag) return;
+    
+    fprintf(f, "\n//EBNF to create railroad diagram\n");
+
+    k = 1;
+    for (i = 2; i < nrules; ++i) {
+        name = symbol_name[rlhs[i]];
+        skip_rule = name[0] == '$';
+        if(!skip_rule) {
+            if (rlhs[i] != rlhs[i-1]) {
+                if (i != 2) fprintf(f, "\n");
+                fprintf(f, "%s ::=", name);
+                spacing = strlen(name) + 1; }
+            else {
+                j = spacing;
+                while (--j >= 0) putc(' ', f);
+                putc('|', f); }
+        }
+	while (ritem[k] >= 0) {
+	    if(!skip_rule && symbol_name[ritem[k]][0] != '$') fprintf(f, " %s", symbol_name[ritem[k]]);
+	    ++k; }
+	++k;
+	putc('\n', f); }
+    fputs("\n", f);
+}
+
 extern int read_errs;
 
 void reader() {
@@ -2027,5 +2060,6 @@ void reader() {
   free_tags();
   pack_grammar();
   free_symbols();
+  print_grammar_ebnf();
   print_grammar();
 }
@gwideman
Copy link

gwideman commented May 8, 2023

Those railroad diagrams are very satisfying! Nice addition!

@satya-das
Copy link
Owner

Sorry that I didn't get a chance to look at it before. This is indeed very nice. I will suggest to open a PR for https://github.com/ChrisDodd/btyacc with the changes mentioned here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants