// This file is part of the AspectC++ compiler 'ac++'. // Copyright (C) 1999-2003 The 'ac++' developers (see aspectc.org) // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public // License along with this program; if not, write to the Free // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, // MA 02111-1307 USA #ifndef __MatchExpr_h__ #define __MatchExpr_h__ #include "Puma/ErrorStream.h" #include "Puma/CFunctionInfo.h" #include "Puma/CClassInfo.h" #include "Puma/Location.h" using namespace Puma; #include "MatchType.h" #include "MatchTemplateArg.h" #include "MatchName.h" // this is an abstraction for AspectC++ match expressions. These expressions // describe signature patters, which can be matched agains the signatures // of C++ objects. class MatchExpr { // object state enum State { NEW = 0, // this object is not initialized, yet NORMAL = 1, // this is a valid match expression, ready for 'match' calls // state of the expression ( < 0 means an error code) ERR_NO_DECL_SPEC = -1, // no declaration specifier given ERR_EMPTY_MATCH_EXPR = -2, // neither decl spec nor declarator given ERR_TOKENS_AFTER_END = -3, // tokens after end of match expression ERR_INVALID_DOT = -4, // invalid use of "..." ERR_INVALID_DECLARATOR = -5, // invalid declarator ERR_MISSING_BRACKET = -6, // missing bracket ERR_MISSING_DECL_ID = -7, // missing declarator id (the name) ERR_DECL_NOT_ABSTRACT = -8, // argument declarator not abstract ERR_ARG_AFTER_ELLIPSES = -9, // argument after "..." ERR_INVALID_ARG_LIST = -10, // invalid argument list ERR_INVALID_ARRAY = -11, // array size is neither "%" nor int constant ERR_DUP_CV = -12, // duplicated const or volatile ERR_DUP_SIGN = -13, // duplicated signed or unsigned ERR_CONF_SIZE = -14, // conflicting short and long ERR_INVALID_TYPE = -15, // invalid type ERR_INVALID_OPER = -16, // invalid operator name ERR_TEMPLATE_ARG_LIST = -17, // error in template arguments ERR_DUP_FCT_SPEC = -18, // duplicate virtual, inline, or explicit ERR_INVALID_FCT_SPEC = -19 // only functions can have function specifiers } _state; // match expression type enum Type { ATTRIBUTE, FUNCTION, TYPE } _expr_type; // primitive types enum PrimType { PRIM_NONE, PRIM_CHAR, PRIM_INT, PRIM_VOID, PRIM_BOOL, PRIM_FLOAT, PRIM_DOUBLE, PRIM_WCHAR_T }; // const or volatile qualifiers enum CVQualifier { QUAL_NONE = 0, QUAL_CONST = 1, QUAL_VOLATILE = 2 } ; // function specifiers, currently only 'virtual' is supported by the parser enum FctSpec { FCT_NONE = 0, FCT_VIRTUAL = 1, FCT_INLINE = 2, FCT_EXPLICIT = 4 } _fct_spec; // type used for parsing and analysing the declaration specifier sequence struct DeclSpecs { CVQualifier _qual; // bitfield with const/volatile qualifiers FctSpec _fct_spec; // bitfield with function specifiers int _sign; // -1, 0, +1 int _size; // -1 = short, 0 = no change, 1 = long, 2 = long long, ... bool _allow_name; PrimType _type; MatchName _name; DeclSpecs () : _qual (QUAL_NONE), _fct_spec (FCT_NONE), _sign (0), _size (0), _allow_name (true), _type (PRIM_NONE) {} }; // the name pattern of the match expression MatchName _name; MatchTypeRef _type; public: // constructors/destructor inline MatchExpr (); inline MatchExpr (ErrorStream &err, Location loc, const char *str); // parse a match expression string // complain about errors => result false bool parse (ErrorStream &err, Location loc, const char *str); // check if a certain signature is matched by this expression, // obj is passed to check the name part of the signature // true is returned if the signature is matched inline bool matches (CTypeInfo *type, CObjectInfo *obj); // check the state of this match expression inline bool error () const; inline bool is_function () const; inline bool is_attribute () const; inline bool is_type () const; private: // internal parser functions that analyse a match expr string bool parse_match_expr (const char *&str); bool parse_declaration (const char *&str, bool abstract, MatchTypeRef &type); bool parse_decl_spec_seq (const char *&str, MatchTypeRef &type, FctSpec &fs); bool parse_decl_spec (const char *&str, DeclSpecs &ds); bool parse_nested_name (const char *&str, MatchName &match_name); bool parse_nested_name_elem (const char *&str, MatchName &match_name); bool parse_opt_template_argument_list (const char *&str, MatchTemplateArgList *&mtal); bool parse_template_argument_list (const char *&str, MatchTemplateArgList &mtal); bool parse_template_argument (const char *&str, MatchTemplateArg *&mta); bool parse_dec_literal (const char *&str, long long &val); bool parse_declarator (const char *&str, bool abstract, MatchTypeRef &type); bool skip_nested_declarator (const char *&str); bool parse_declarator_post (const char *&str, MatchTypeRef &type); bool parse_ptr_operator (const char *&str, MatchTypeRef &type); bool parse_declarator_id (const char *&str, MatchName &match_name); bool parse_conv_id (const char *&str, MatchTypeRef &type); bool parse_operator_id (const char *&str, MatchName::Operator &op); bool parse_fct_args (const char *&str, vector &args, bool &va); bool parse_ellipses (const char *&str); inline void skip_blanks (const char *&str) const; inline bool next_word (const char *word, const char *&str) const; inline bool is_id (char c) const; }; // implementations of inline constructors/destructor inline MatchExpr::MatchExpr () : _state (NEW) {} inline MatchExpr::MatchExpr (ErrorStream &err, Location loc, const char *str) : _state (NEW) { parse (err, loc, str); } // check the state of this match expression inline bool MatchExpr::error () const { return _state < 0; } inline bool MatchExpr::is_function () const { return _expr_type == FUNCTION; } inline bool MatchExpr::is_attribute () const { return _expr_type == ATTRIBUTE; } inline bool MatchExpr::is_type () const { return _expr_type == TYPE; } // check if a certain signature is matched by this expression // true is returned if the signature is matched inline bool MatchExpr::matches (CTypeInfo *ctype, CObjectInfo *obj) { assert (_state == NORMAL && !_type.is_undefined ()); if (!_type.matches (ctype)) return false; if (!obj || is_type ()) return true; if (!_name.matches (obj)) return false; if (is_function () && (_fct_spec & FCT_VIRTUAL) != 0) { if (!(obj->isVirtual () || obj->FunctionInfo ()->overridesVirtual ())) return false; } return true; } #endif // __MatchExpr_h__