Giter Site home page Giter Site logo

satya-das / cppparser Goto Github PK

View Code? Open in Web Editor NEW
262.0 8.0 34.0 16.97 MB

A library to parse C/C++ source as AST

License: MIT License

C++ 73.77% C 7.05% Lex 0.07% Yacc 0.19% CMake 0.01% Objective-C 18.91% Shell 0.01%
parsing ast cpp-ast back-tracking-parsing c-plus-plus-parsing cplusplus-ast cplusplus parser-library cppast cpp-parser

cppparser's Introduction

  • ๐Ÿ‘‹ Hi, Iโ€™m Satya Das
  • ๐Ÿ‘€ Iโ€™m interested in C++ and low level stuff
  • ๐ŸŒฑ Iโ€™m currently learning Parsing Technique and writing a C++ Parser
  • ๐Ÿ“ซ I can be reached at [email protected]

cppparser's People

Contributors

satya-das avatar satyaranjandas-tomtom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cppparser's Issues

Does this library support C++ attributes?

From what I see, cppparser doesn't recognize the [[ns::attribute]] syntax at all.
Am I unfortunately right, or is there any way to somehow enable attribute declaration parsing?
If I'm right, are there any plans to implement attribute parsing in the near future?

Can not process "goto cleanup"

Hi,
Could you take attention to "goto cleanup" parsing?


{
goto cleanup:
....
cleanup:
cleanup();
return;
}

Error: Unexpected token ':', while in context=1, found at line#146
cleanup:

Best Regards,
bring.zhang

segfault on a very large source file

I get a segfault when trying to analyze this file: https://github.com/mmomtchev/node-magickwand/raw/84e1cdff82aae838233202e76b9ca01815e9ebec/Magick%2B%2B.cxx

I am using a very basic walking of the outermost members:

#include "cppparser/pub/cppparser.h"
#include <stdio.h>
#include <boost/filesystem.hpp>

namespace fs = boost::filesystem;

int main() {
  CppParser  parser;
  const auto testFilePath = fs::path(__FILE__).parent_path() / "Magick++.cxx";
  const auto ast          = parser.parseFile(testFilePath.string());

  const auto& members = ast->members();

  for (const auto &m : members) {
    if (m->objType_ == CppObjType::kFunction)
      printf("%s\n", ((CppFunctionEPtr)m)->name_.c_str());
  }
}

The output is:

Error: Unexpected 'SWIG_AddCast', while in context=ctxGeneral(1), found at line#383
SWIGINTERNINLINE int SWIG_AddCast
                     ^
Segmentation fault

Operator precedence is incorrect with '>'

(a > b || c) is being parsed as (a > (b || c)) when it should be ((a > b) || c).
Similarly, (a > b && c) is being parsed as (a > (b && c)) rather than ((a > b) && c).
It appears to just be the > operator. The other comparison operators seem to be OK.

using namespace support

Could you add the code below in order to support the using namespace directive?

diff --git a/pub/cppwriter.h b/pub/cppwriter.h
index 5b9e3a81..e2541d48 100644
--- a/pub/cppwriter.h
+++ b/pub/cppwriter.h
@@ -66,6 +66,9 @@ public:
   virtual void emitUsingDecl(const CppUsingDecl* usingDecl,
                              std::ostream&       stm,
                              CppIndent           indentation = CppIndent()) const;
+  virtual void emitUsingNamespaceDecl(const CppUsingNamespaceDecl* usingDecl,
+                                      std::ostream&                stm,
+                                      CppIndent                    indentation = CppIndent()) const;
   virtual void emitTypedefList(const CppTypedefList* typedefList,
                                std::ostream&         stm,
                                CppIndent             indentation = CppIndent()) const;
diff --git a/src/cppwriter.cpp b/src/cppwriter.cpp
index 89034bcd..2ed6a738 100644
--- a/src/cppwriter.cpp
+++ b/src/cppwriter.cpp
@@ -106,6 +106,8 @@ void CppWriter::emit(const CppObj* cppObj, std::ostream& stm, CppIndent indentat
       return emitDocComment((CppDocComment*) cppObj, stm, indentation);
     case CppObjType::kUsingDecl:
       return emitUsingDecl((CppUsingDecl*) cppObj, stm, indentation);
+    case CppObjType::kUsingNamespaceDecl:
+      return emitUsingNamespaceDecl((CppUsingNamespaceDecl*) cppObj, stm, indentation);
     case CppObjType::kTypedefName:
       return emitTypedef((CppTypedefName*) cppObj, stm, indentation);
     case CppObjType::kTypedefNameList:
@@ -411,6 +413,13 @@ void CppWriter::emitUsingDecl(const CppUsingDecl* usingDecl,
   stm << ";\n";
 }
 
+void CppWriter::emitUsingNamespaceDecl(const CppUsingNamespaceDecl* usingDecl,
+                                       std::ostream&                stm,
+                                       CppIndent                    indentation /* = CppIndent()*/) const
+{
+  stm << indentation << "using namespace " << usingDecl->name_ << ";\n";
+}
+
 void CppWriter::emitTypedefList(const CppTypedefList* typedefList,
                                 std::ostream&         stm,
                                 CppIndent             indentation /* = CppIndent()*/) const

Issue with variable initializer list...

I have this snippet of code and I keep getting the error "Error: Unexpected '.', while in context=ctxGeneral(1), found at line#624". GCC/Clang both support this with out issue.

void processor64::pipe_thread (void)
{
pipeChannel pipe = {.raw = 0};
}

Cleanup deps?

Hi, I would really like to use your parser even if it is not done yet. I find the deps a bit complicated though. For instance boost filesystem could be removed since you use c++17 anyway which comes with filesystem.

Grammar railroad diagram

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

Build on Linux with local Boost

Ubuntu 22.04 supplies Boost 1.74. I would like to link the cppparser with it. Can we have this supported?
The code below does this.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f9c14db5..1c5c275a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@ project(cppparser)
 
 enable_testing()
 
-include("../common/cmake/conf.cmake")
+#include("../common/cmake/conf.cmake")
 
 set(CMAKE_CXX_STANDARD 17)
 
@@ -17,9 +17,18 @@ add_subdirectory(third_party/btyacc_tp)
 
 add_definitions(-DBOOST_AUTO_LINK_NOMANGLE)
 
-add_subdirectory(../common/third_party/boost_tp/cmake  ${CMAKE_BINARY_DIR}/boost)
+#add_subdirectory(../common/third_party/boost_tp/cmake  ${CMAKE_BINARY_DIR}/boost)
 
-include_directories(../common/third_party)
+#include_directories(../common/third_party)
+
+set(Boost_USE_STATIC_LIBS OFF)
+set(Boost_USE_MULTITHREADED ON)
+set(Boost_USE_STATIC_RUNTIME OFF)
+find_package(Boost COMPONENTS filesystem program_options REQUIRED)
+
+if (NOT EXISTS "${CMAKE_SOURCE_DIR}/src/catch/catch.hpp")
+  file(DOWNLOAD "https://github.com/catchorg/Catch2/releases/download/v2.13.10/catch.hpp" "${CMAKE_SOURCE_DIR}/src/catch/catch.hpp")
+endif()
 
 #############################################
 ## CppParser
@@ -72,18 +81,18 @@ set(CPPPARSER_SOURCES
 )
 
 add_library(cppparser STATIC ${CPPPARSER_SOURCES})
-add_dependencies(cppparser btyacc boost_filesystem boost_program_options)
+#add_dependencies(cppparser btyacc boost_filesystem boost_program_options)
 target_link_libraries(cppparser
 	PUBLIC
-		boost_filesystem
-		boost_program_options
+		${Boost_FILESYSTEM_LIBRARY}
+		${Boost_PROGRAM_OPTIONS_LIBRARY}
 		boost_system
 )
 target_include_directories(
 	cppparser
 	PUBLIC
 		pub
-		../common/third_party/boost_tp
+		#../common/third_party/boost_tp
 	PRIVATE
 		hack
 )
diff --git a/third_party/btyacc_tp/CMakeLists.txt b/third_party/btyacc_tp/CMakeLists.txt
index a1cfa01d..c675f138 100644
--- a/third_party/btyacc_tp/CMakeLists.txt
+++ b/third_party/btyacc_tp/CMakeLists.txt
@@ -1,4 +1,4 @@
-include("../../../common/cmake/conf.cmake")
+#include("../../../common/cmake/conf.cmake")
 
 project(btyacc)
 

Also please note that the file(DOWNLOAD ...) directive is used in order to download catch.hpp. Thus I got rid of https://github.com/satya-das/common.git repo usage.

How to traverse the ast tree?

Say I have two source code file1.cpp and file2.cpp written in C++, I want to know the difference code between them and locate this difference code to the function. I kind of get that this cppparser is able to get ast of the source code, but i'm still confused how to traverse the ast tree and compare two ast trees from different source code? Could anyone help me with this?

Constructor initializers are parsed incorrectly

The code below is parsed incorrectly

    class Base {
    public:
        Base(std::vector<int> columns) {}
    };

    class Derived {
    public:
        Derived() :  Base(std::vector<int>{1, 2, 3}) {}
    };

The std::vector<int>{1, 2, 3} is parsed as a function call.

(gdb) p *memInit.second
{
      <CppObj> = {_vptr.CppObj = 0x5555556028c0 <vtable for CppExpr+16>, objType_ = CppObjType::kExpression, accessType_ = CppAccessType::kUnknown, owner_ = 0x0}, 
      static kObjectType = CppObjType::kExpression, 
      expr1_ = {
            {atom = 0x5555556760d0, expr = 0x5555556760d0, lambda = 0x5555556760d0, varType = 0x5555556760d0}, 
            type = CppExprAtom::kExpr
      }, 
      expr2_ = {
            {atom = 0x555555676050, expr = 0x555555676050, lambda = 0x555555676050, varType = 0x555555676050}, 
            type = CppExprAtom::kExpr
      }, 
      expr3_ = {
            {atom = 0x0, expr = 0x0, lambda = 0x0, varType = 0x0}, 
            type = CppExprAtom::kExpr
      }, 
      oper_ = kFunctionCall, 
      flags_ = 0
}

Therefore, once we use a CppWriter, the result is the following:

        Derived()
            : Base(std::vector<int>(1, 2, 3))
        {
        }

Static arrays initialization causes parse errors

There are some cases with initializing static arrays in sequences which the parser fails to process.

Example 1:

int main()
{
  int variable, array_one[100], array_two[500];
  return 0;
}

produces:

./cppparsertest -p failed_testcases/many_arrays.cpp 
Error: Unexpected '[', while in context=ctxGeneral(1), found at line#2
	int variable, array_one[100], array_two[

Example 2:

int main()
{
  int variable = 0, array[100];
  return 0;
}

produces:

./cppparsertest -p failed_testcases/one_array.cpp 
Error: Unexpected '[', while in context=ctxGeneral(1), found at line#2
	int variable=0, array[

At the same time it parses these examples:

int main()
{
  int variable_one = 0, variable_two = 1;
  return 0;
}
int main()
{
  int array_one[500], array_two[500];
  return 0;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.