///////////////////////////////////////////////////////////////////////////// // Name: No names yet. // Purpose: To provide a simple _framework_ // for series of source code parsers with // compatible interfaces // Author: Aleksandras Gluchovas // Modified by: AG on 28/12/98 // Created: 22/09/98 // RCS-ID: $Id: srcparser.h 41718 2006-10-08 14:34:37Z VZ $ // Copyright: (c) Aleskandars Gluchovas // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef __SRCPARSER_G__ #define __SRCPARSER_G__ #if defined( wxUSE_TEMPLATE_STL ) #include #ifdef WIN32 #include #else #include #include #endif #else #include "wx/string.h" #include "wxstlvec.h" #endif #include "markup.h" // markup tags used in spOperator::GetFullName() // these methods are used for debugging only and disappear in the release build #ifdef __WXDEBUG__ #define DECLARE_DUMP virtual void DumpThis(const wxString& indent) const; #else #define DECLARE_DUMP #endif // context class list in "inside-out" order : class spContext; class spParameter; class spAttribute; class spOperation; class spEnumeration; class spTypeDef; class spPreprocessorLine; class spClass; class spNameSpace; class spFile; // source context visibilities enum SRC_VISIBLITY_TYPES { SP_VIS_PUBLIC, SP_VIS_PROTECTED, SP_VIS_PRIVATE }; // class types enum SP_CLASS_TYPES { SP_CLTYPE_INVALID, SP_CLTYPE_CLASS, SP_CLTYPE_TEMPLATE_CLASS, SP_CLTYPE_STRUCTURE, SP_CLTYPE_UNION, SP_CLTYPE_INTERFACE }; // inheritance types enum SP_INHERITANCE_TYPES { SP_INHERIT_VIRTUAL, SP_INHERIT_PUBLIC, SP_INHERIT_PRIVATE }; // proprocessor definitions types (specific to C++ code) enum SP_PREP_DEFINITION_TYPES { SP_PREP_DEF_DEFINE_SYMBOL, SP_PREP_DEF_REDEFINE_SYMBOL, SP_PREP_DEF_INCLUDE_FILE, SP_PREP_DEF_OTHER }; // common context types #define SP_CTX_UNKNOWN 0x000 #define SP_CTX_FILE 0x001 #define SP_CTX_NAMESPACE 0x002 #define SP_CTX_CLASS 0x004 #define SP_CTX_TYPEDEF 0x008 #define SP_CTX_PREPROCESSOR 0x010 #define SP_CTX_ENUMERATION 0x020 #define SP_CTX_ATTRIBUTE 0x040 #define SP_CTX_OPERATION 0x080 #define SP_CTX_PARAMETER 0x100 // other (custom) context codes may be defined elsewere, however they should // not clash with above codes for common type and also should not // exceed 16-bits of in value // masks all context types (up to 16 custom context can be defined) #define SP_CTX_ANY 0xFFFF class spComment; #if defined( wxUSE_TEMPLATE_STL ) // context members typedef vector MMemberListT; // comments list typedef vector MCommentListT; // list of parameters typedef vector MParamListT; // wxString list typedef vector StrListT; #else typedef spContext* spContextPtrT; typedef spComment* spCommentPtrT; typedef spParameter* spParameterPtrT; typedef WXSTL_VECTOR_SHALLOW_COPY(spContextPtrT) MMemberListT; typedef WXSTL_VECTOR_SHALLOW_COPY(spCommentPtrT) MCommentListT; typedef WXSTL_VECTOR_SHALLOW_COPY(spParameterPtrT) MParamListT; typedef WXSTL_VECTOR_SHALLOW_COPY(wxString) StrListT; #endif // base class for all visitors of source code contents class spVisitor { protected: bool mSiblingSkipped; bool mChildSkipped; int mContextMask; spContext* mpCurCxt; public: // methods invoked by context // method invoked from user's controling code // to visit all nodes staring at the given context. // Content is sorted if requrired, see comments // spClass on sorting the class members void VisitAll( spContext& atContext, bool sortContent = true ); // methods invoked by visitor // goes to the next context in the outter scope // NOTE:: should not be invoked more than once while // visiting certain context void SkipSiblings(); // prevents going down into the contexts contained by // the current context // NOTE:: the same as above void SkipChildren(); // can be called only in from visiting procedure void RemoveCurrentContext(); // method enables fast filtered traversal // of source content, e.g. collecting only classes, // or only global functions // arg. context - can contain combination of contexts concatinated // with bitwise OR, e.g. SP_CTX_CLASS | SP_CTX_NAMESPACE // // method can be invoked from the user's controling as well as // from within the visting procedure void SetFilter( int contextMask ); // methods should be implemneted by specific visitor: // NOTE:: Do not confuse visiting with parsing, first // the source is parsed, and than can be visited // multiple times by variouse visitors (there can // be more the one visitor visiting content at a time) virtual void VisitFile( spFile& WXUNUSED(fl) ) {} virtual void VisitNameSpace( spNameSpace& WXUNUSED(ns) ) {} virtual void VisitClass( spClass& WXUNUSED(cl) ) {} virtual void VisitEnumeration( spEnumeration& WXUNUSED(en) ) {} virtual void VisitTypeDef( spTypeDef& WXUNUSED(td) ) {} virtual void VisitPreprocessorLine( spPreprocessorLine& WXUNUSED(pd) ) {} virtual void VisitAttribute( spAttribute& WXUNUSED(attr) ) {} virtual void VisitOperation( spOperation& WXUNUSED(op) ) {} virtual void VisitParameter( spParameter& WXUNUSED(param) ) {} virtual void VisitCustomContext( spContext& WXUNUSED(ctx) ) {} virtual ~spVisitor() { } }; // stores one section of comments, // multiple sections can be put to geather // and attached to some context class spComment { public: wxString m_Text; bool mIsMultiline; // multiline comments ar those with /**/'s // true, if these was an empty empty // line above single line comment bool mStartsPar; public: bool IsMultiline() const; bool StartsParagraph() const; wxString& GetText(); // contstant version of GetText() wxString GetText() const; }; // abstract base class for common (to most languages) code // contexts (constructs), e.g file, namespace, class, operation, // etc class spContext { protected: // "linked" list of comments belonging to this context MCommentListT mComments; // NULL, if this is file context MMemberListT mMembers; // NULL, if this is top-most context spContext* m_pParent; // points to context object, where the this context // was originally declared, meaning that this object // is redeclaration (or if in the case of operation // this context object most probably referres to the // implemnetation in .cpp file for example) // is NULL, if this object referres to the first occurence // of the context spContext* mpFirstOccurence; // used, to avoid excessive sorting of context's agreggates bool mAlreadySorted; public: // source line number, (-1) if unknown int mSrcLineNo; // offset of context in the source file, (-1) if unknown int mSrcOffset; // lentgh of the context in characters, (-1) if unknown int mContextLength; // source line number, in which this cotext ends, (-1) if unknown int mLastScrLineNo; // fields are valid, if the may contain other contexts nested inside int mHeaderLength; int mFooterLength; // zero-based index of the first character of // this context in the source line, (-1) if unknown int mFirstCharPos; // zero-based index of the first character of // this context in the last source line of this context, (-1) if unknown int mLastCharPos; // see SRC_VISIBLITY_TYPES enumeration int mVisibility; // true, if context does not really exist in the source // but was created by external tools (e.g. forward engineering) bool mIsVirtualContext; bool mVirtualContextHasChildren; // body of the context in case (mIsVirtual == true) wxString mVirtualContextBody; wxString mVittualContextFooter; // e.g. can be used by documentation generator to store // reference to section object void* mpUserData; public: // universal identifier of the context (e.g. class name) wxString m_Name; public: // default constructor spContext(); // automatically destorys all aggregated contexts // (thus, it's enought to call destructor of root-context) virtual ~spContext(); // see mUererData member; void* GetUserData() { return mpUserData; } // sets untyped pointer to user data void SetUserData( void* pUserData ) { mpUserData = pUserData; } // searches the whole context tree for the cotnexts // which match given masks, pust results into lst array void GetContextList( MMemberListT& lst, int contextMask ); // used by default visitor's implementation bool IsSorted(); /*** forward/reverse ingineering fecilities ***/ bool PositionIsKnown(); bool IsVirtualContext(); bool VitualContextHasChildren(); void SetVirtualContextBody( const wxString& body, bool hasChildren = false, const wxString& footer = wxEmptyString ); wxString GetVirtualContextBody(); wxString GetFooterOfVirtualContextBody(); // can be overriden by top-level context classes // to find-out ot the source-fragment of this // context using it's position information virtual wxString GetBody( spContext* pCtx = NULL ); virtual wxString GetHeader( spContext* pCtx = NULL ); // true, if there is at least one entry // in the comment list of this context bool HasComments(); MCommentListT& GetCommentList() { return mComments; } const MCommentListT& GetCommentList() const { return mComments; } // should be overriden, if the context supports sorting // of it's members virtual void SortMembers() {} // returns identifier of this context inline wxString& GetName() { return m_Name; } // returns -1, if souce line # is unknow inline int GetSourceLineNo() { return mSrcLineNo; } // see comments on mpFirstOccurence member variable bool IsFirstOccurence(); spContext* GetFirstOccurence(); // returns not-NULL value if this context // is aggregated by another cotnext spContext* GetOutterContext(); // perhaps more intuitive alias for `GetOutterContext()' inline spContext* GetParent() { return m_pParent; } bool HasOutterContext(); // add one aggregate (or child) into this context void AddMember ( spContext* pMember ); MMemberListT& GetMembers(); // append comment to the comment list decribing // this context void AddComment( spComment* pComment ); // returns NULL, if the context with the given // name and type is not contained by this context // and it's children. Children's children are not // searched recursivelly if searchSubMembers is false spContext* FindContext( const wxString& identifier, int contextType = SP_CTX_ANY, bool searchSubMembers = true ); // removes this context from it's parent // (NOTE:: context should have an outter cotnext // to when this method is called, otherwise removal // will result assertion failure) void RemoveThisContext(); // returns true, if this object is aggregated in the file bool IsInFile(); // true, if outter context is a namespace bool IsInNameSpace(); // true, if outter context is a class bool IsInClass(); // true, if outter cotext is an operation (true for "spParameter"s) bool IsInOperation(); // true if the context is public bool IsPublic() const { return mVisibility == SP_VIS_PUBLIC; } // NOTE:: method returns not the type of this object // but the file/namespace/class/operation or file in which this // attribute is contained. First, check for the type of // context using the above method. // Requiering container which does not exist, will result // in assertion failure spClass& GetClass(); spFile& GetFile(); spNameSpace& GetNameSpace(); spOperation& GetOperation(); // each new context should override this method // to return it's specific type virtual int GetContextType() const { return SP_CTX_UNKNOWN; } // perhaps more intuitive short-cut inline int GetType() { return GetContextType(); } // cast this context to the desired type - returns NULL if type is wrong spAttribute *CastToAttribute() { return GetContextType() == SP_CTX_ATTRIBUTE ? (spAttribute *)this : NULL; } // derived classes override this to invoke VisitXXX method // which corresponds to the class of specific context, // - this is what the "Visitor" pattern told us ^) // if method is not overriden, then it's probably user-defined // custom context virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitCustomContext( *this ); }; // called by visitors, to remove given subcontext // of this context object void RemoveChild( spContext* pChild ); void RemoveChildren(); spContext* GetEnclosingContext( int mask = SP_CTX_ANY ); #ifdef __WXDEBUG__ virtual void Dump(const wxString& indent) const; #endif // __WXDEBUG__ DECLARE_DUMP }; // stores information about single argument of operation class spParameter : public spContext { public: // type of argument (parameter) wxString m_Type; // "stringified" initial value wxString m_InitVal; public: virtual int GetContextType() const { return SP_CTX_PARAMETER; } virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitParameter( *this ); } DECLARE_DUMP }; // stores information about member(or global) variable class spAttribute : public spContext { public: // type of the attribute wxString m_Type; // it's initial value wxString m_InitVal; // constantness bool mIsConstant; public: virtual int GetContextType() const { return SP_CTX_ATTRIBUTE; } virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitAttribute( *this ); } DECLARE_DUMP }; class spOperation : public spContext { public: // type of return value wxString m_RetType; // argument list //MParamListT mParams; // true, if operation does not modify // the content of the object bool mIsConstant; // flag, specific to C++ bool mIsVirtual; // true, if definition follows the declaration immediatelly bool mHasDefinition; // scope if any (e.g. MyClass::MyFunction(), scope stirng is "MyClass" ) // usually found along with implementation of the method, which is now skipped wxString mScope; public: spOperation(); // returns full declaration of the operations // (ret val., identifier, arg. list), // arguments are marked up with italic, // default values marked up with bold-italic, // all the rest is marked as bold // NOTE:: this method may be overriden by class // specific to concrete parser, to provide // language-dependent reperesnetation of // operation and it's argumetn list // // the default implementation outputs name in // C++/Java syntax virtual wxString GetFullName(MarkupTagsT tags); virtual int GetContextType() const { return SP_CTX_OPERATION; } virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitOperation( *this ); } DECLARE_DUMP }; // stores infromation about preprocessor directive class spPreprocessorLine : public spContext { public: // prepocessor statement including '#' and // attached multiple lines with '\' character wxString m_Line; int mDefType; // see SP_PREP_DEFINITION_TYPES enumeration public: virtual int GetContextType() const { return SP_CTX_PREPROCESSOR; } virtual int GetStatementType() const { return mDefType; } wxString CPP_GetIncludedFileNeme() const; virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitPreprocessorLine( *this ); } DECLARE_DUMP }; // stores information about the class class spClass : public spContext { public: // list of superclasses/interfaces StrListT m_SuperClassNames; // see SP_CLASS_TYPES enumeration int mClassSubType; // see SP_INHERITANCE_TYPES enumeration int mInheritanceType; // valid if mClassSubType is SP_CLTYPE_TEMPLATE_CLASS wxString mTemplateTypes; // true, if it's and interface of abstract base class bool mIsAbstract; public: // sorts class members in the following order: // // (by "privacy level" - first private, than protected, public) // // within above set // // (by member type - attributes first, than methods, nested classes) // // within above set // // (by identifier of the member) virtual void SortMembers(); virtual int GetContextType() const { return SP_CTX_CLASS; } virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitClass( *this ); } DECLARE_DUMP }; // stores information about enum statement class spEnumeration : public spContext { public: wxString m_EnumContent; // full-text content of enumeration public: virtual int GetContextType() const { return SP_CTX_ENUMERATION; } virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitEnumeration( *this ); } DECLARE_DUMP }; class spTypeDef : public spContext { public: // the original type which is redefined // by this type definition wxString m_OriginalType; public: virtual int GetContextType() const { return SP_CTX_TYPEDEF; } virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitTypeDef( *this ); } DECLARE_DUMP }; // NOTE:: files context may be put to other // file context, resulting in a collection // of parsed file contexts, with a virtual "superfile" class spFile : public spContext { public: // since file name cannot be determined from // source code, filling in this field is optional wxString m_FileName; public: virtual int GetContextType() const { return SP_CTX_FILE; } virtual void AcceptVisitor( spVisitor& visitor ) { visitor.VisitFile( *this ); } DECLARE_DUMP }; //TODO:: comments. class SourceParserPlugin { public: virtual bool CanUnderstandContext( char* cur, char* end, spContext* pOuttterCtx ) = 0; virtual void ParseContext( char* start, char*& cur, char* end, spContext* pOuttterCtx ) = 0; virtual ~SourceParserPlugin() { } }; // abstract interface for source parsers // which can output parsing results in the // form of context-tree, where each node // should be derivative of spContext, (see // above classes) class SourceParserBase { private: // auto-resizing file buffer, created in ParseFile() // to reuse large heap block for multiple parsings char* mpFileBuf; int mFileBufSz; protected: SourceParserPlugin* mpPlugin; protected: // value is set in the derived parser classes int mParserStatus; public: SourceParserBase(); virtual ~SourceParserBase(); // loads entier source file(as text) into memory, // and passes it's contents to ParseAll() method, // memory occupied by source text is released after // parsing is done // // (NOTE:: this is the default implementation), virtual spFile* ParseFile( const char* fname ); // should returns the root-node of the created context tree // (user is responsible for releasing it from the heep) // "end" should point to the (last character + 1) of the // source text area virtual spFile* Parse( char* start, char* end ) = 0; // returns parser "status word" (specific to concrete parser) int GetParserStatus() { return mParserStatus; } void SetPlugin( SourceParserPlugin* pPlugin ); }; #endif