cppparser icon indicating copy to clipboard operation
cppparser copied to clipboard

Grammar railroad diagram

Open mingodad opened this issue 2 years ago • 2 comments

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();
 }

mingodad avatar Jan 17 '23 13:01 mingodad

Those railroad diagrams are very satisfying! Nice addition!

gwideman avatar May 08 '23 00:05 gwideman

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.

satya-das avatar May 25 '23 16:05 satya-das

cppparser is now using latest btyacc that has this change already. Closing this issue.

satya-das avatar Oct 16 '24 09:10 satya-das