2017-02-21 20:32:40 +01:00
#
2023-01-01 22:27:09 +01:00
# Copyright (C) 2006-2023 Matthias Koefferlein
2017-02-21 20:32:40 +01:00
#
# 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
class Module
def def_initializer ( * args )
self . class_eval <<END
def initialize ( #{args.join(", ")})
#{args.map { |arg| "@#{arg} = #{arg}" }.join("\n")}
end
def initialize_copy ( other )
# TODO: is there a better way to check whether dup can be used?
# Implement Hash?
#{args.map { |arg| "a = other.#{arg}\n"+
" if a.is_a?(TrueClass) || a.is_a?(FalseClass) || a.is_a?(NilClass) || a.is_a?(Fixnum) || a.is_a?(Float) || a.is_a?(Symbol) \n " +
" @ #{ arg } = a \n " +
" elsif a.is_a?(Array) \n " +
" @ #{ arg } = a.collect { |aa| aa.dup } \n " +
" else \n " +
" @ #{ arg } = a.dup \n " +
" end "
} . join ( " \n " ) }
end
END
end
end
# @brief The base class for all CPP objects
class CPPObject
end
# @brief Denotes type nesting wrappers
# Type nesting provide a modification the renders a different type
# for the inner "user" of the type. For example:
# "int **x" starts with "int", adds a pointer, adds another pointer and
# ends at "x" (the symbol). "int" is the "concrete type", the two
# pointers are type wrappers and "x" is the innermost elements.
# The type s read from the inside out: "x" is a pointer to a pointer to an int.
class CPPOuterType < CPPObject
end
# @brief An array specification
# @attribute inner The inner type (the type which makes use of the array)
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
class CPPArray < CPPOuterType
attr_accessor :inner
def_initializer :inner
def to_s
if self . inner . is_a? ( CPPPointer )
" ( " + self . inner . to_s + " ) [] "
else
self . inner . to_s + " [] "
end
end
def dump ( i )
i + " CPPArray \n " + i + " inner: \n " + self . inner . dump ( i + " " )
end
end
# @brief A function specification
# @attribute inner The inner type (which makes use of the function)
# @attribute args The function arguments
# @attribute cv A const/voilatile specification if the function is a method (:const, :volatile)
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
# "args" is an array of CPPType or CPPInitializedType objects, optionally terminated with
# a CPPEllipsis.
# "cv" is a CPPCV object.
class CPPFunc < CPPOuterType
2021-11-27 15:29:38 +01:00
attr_accessor :inner , :args , :cv , :ref
def_initializer :inner , :args , :cv , :ref
2017-02-21 20:32:40 +01:00
def to_s
a = self . args
a || = [ ]
if ! a . is_a? ( Array )
a = [ a ]
end
2021-11-27 15:29:38 +01:00
self . inner . to_s + " ( " + a . join ( " , " ) + " ) " + ( self . cv ? " " + self . cv . to_s : " " ) + ( self . ref ? " " + self . ref . to_s : " " )
2017-02-21 20:32:40 +01:00
end
def dump ( i )
i + " CPPFunc \n " + i + " inner: \n " + self . inner . dump ( i + " " ) + " \n " +
i + " cv: " + self . cv . to_s + " \n " +
2021-11-27 15:29:38 +01:00
i + " ref: " + self . ref . to_s + " \n " +
2017-02-21 20:32:40 +01:00
i + " args: \n " + ( self . args || [ ] ) . collect { | f | f . dump ( i + " " ) } . join ( " \n " )
end
end
# @brief A pointer declaration
# @attribute inner The inner type which sees the outer type converted into a pointer
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
class CPPPointer < CPPOuterType
attr_accessor :inner
def_initializer :inner
def to_s
" * " + self . inner . to_s
end
def dump ( i )
i + " CPPPointer \n " + i + " inner: \n " + self . inner . dump ( i + " " )
end
end
# @brief A reference declaration
# @attribute inner The inner type which sees the outer type converted into a reference
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
class CPPReference < CPPOuterType
attr_accessor :inner
def_initializer :inner
def to_s
" & " + self . inner . to_s
end
def dump ( i )
i + " CPPReference \n " + i + " inner: \n " + self . inner . dump ( i + " " )
end
end
# @brief A member/method pointer declaration
# @attribute qid The class of which a member/method is addressed (a CPPQualifiedId object)
# @attribute inner The inner type which sees the outer type converted into a member/method pointer
# @attribute cv A CPPCV object describing whether the method is a const or volatile one
# Functions are converted to method pointers, plain type into member pointers.
# "inner" is either another CPPOuterType or a CPPQualifiedId (the innermost)
# part.
class CPPMemberPointer < CPPOuterType
attr_accessor :qid , :inner , :cv
def_initializer :qid , :inner , :cv
def to_s
self . qid . to_s + " ::* " + self . inner . to_s + ( self . cv ? " " + self . cv . to_s : " " )
end
def dump ( i )
i + " CPPMemberPointer \n " + i + " inner: \n " + self . inner . dump ( i + " " ) +
i + " cv: \n " + self . cv . dump ( i + " " ) +
i + " qid: " + self . qid . to_s
end
end
# @param Adds const or volatile declaration
# @attribute cv :const or :volatile
# @attribute inner The inner expression which sees the const/volatile declaration
class CPPCV < CPPOuterType
attr_accessor :cv , :inner
def_initializer :cv , :inner
def to_s
( self . cv ? ( self . cv . to_s + " " ) : " " ) + self . inner . to_s
end
def dump ( i )
i + " CPPCV \n " +
i + " cv: " + self . cv . to_s + " \n " +
i + " inner: \n " + self . inner . dump ( i + " " )
end
end
def CPPCV :: wrap ( cv , inner )
cv ? CPPCV :: new ( cv , inner ) : inner
end
# @brief A constant uses as a template instance argument
# @attribute value A string giving the value
class CPPConst < CPPObject
attr_accessor :value
def_initializer :value
def to_s
self . value
end
def dump ( i )
i + " CPPConst \n " + i + " value: " + self . value . to_s
end
end
# @brief A class the template instance arguments
# @attribute args An array of CPPConst (for constants) or CPPType objects (for types)
# This class is used for both template instances or declarations.
class CPPTemplateArgs < CPPObject
attr_accessor :args
def_initializer :args
def to_s
self . args . collect { | a | a . to_s } . join ( " , " )
end
def dump ( i )
i + " CPPTemplateArgs \n " +
i + " args: \n " + ( self . args || [ ] ) . collect { | a | a . dump ( i + " " ) } . join ( " \n " )
end
end
# @brief An class or namespace name, optionally with template arguments
# @attribute id The basic id (a string)
# @attribute template_args A CPPTemplateArgs object describing the template arguments or nil, if it does not describe a template instance or declaration
class CPPId < CPPObject
attr_accessor :id , :template_args
def_initializer :id , :template_args
def to_s
ta = self . template_args . to_s
if ta =~ / >$ /
ta += " "
end
self . id + ( self . template_args ? ( " < " + ta + " > " ) : " " )
end
def dump ( i )
i + " CPPId \n " +
i + " id: " + self . id . to_s +
i + " template_args: \n " + self . template_args . dump ( i + " " )
end
end
# @brief An anonymous ID
# This object is used in place of CPPQualifiedId if no name is given
class CPPAnonymousId < CPPObject
def to_s
" "
end
def dump ( i )
i + " CPPAnonymousId "
end
end
# @brief An id, optionally qualified by a namespace
# @attribute global If true, the Id is rooted in the global namespace
# @attribute parts A sequence of CPPId objects forming the namespace sequence
class CPPQualifiedId < CPPObject
attr_accessor :global , :parts
def_initializer :global , :parts
def to_s
( self . global ? " :: " : " " ) + ( self . parts || [ ] ) . collect { | p | p . to_s } . join ( " :: " )
end
def dump ( i )
n = ( self . global ? " :: " : " " ) + ( self . parts || [ ] ) . collect { | p | " [ " + p . to_s + " ] " } . join ( " :: " )
i + " CPPQualifiedId ( " + n + " ) "
end
end
# @brief A "plain old type" (double, float, int, char, ...)
# @attribute signed Is nil, :signed or :unsigned (for the types supporting that)
# @attribute length Is nil, :short, :long or :longlong for the types supporting that
# @attribute type The basic type (:int, :char, :bool, :float, :double)
class CPPPOD < CPPObject
attr_accessor :signed , :length , :type
def_initializer :signed , :length , :type
def to_s
s = " "
if self . signed == :signed
s += " signed "
elsif self . signed == :unsigned
s += " unsigned "
end
if self . length == :short
s += " short "
elsif self . length == :long
s += " long "
elsif self . length == :longlong
s += " long long "
end
s + self . type . to_s
end
def dump ( i )
i + " CPPPOD ( " + self . to_s + " ) "
end
end
# @brief A base class declarations
# @attribute visibility :default, :public, :private or :protected
# @attribute virtual Is true, if the class is a virtual base class
# @attribute class_id A CPPQualifiedId object pointing to the base class
class CPPBaseClass < CPPObject
attr_accessor :visibility , :virtual , :class_id
def_initializer :visibility , :virtual , :class_id
def to_s
( self . visibility ? self . visibility . to_s + " " : " " ) + ( self . virtual ? " virtual " : " " ) + self . class_id . to_s
end
def dump ( i )
i + " CPPBaseClass \n " +
i + " visibility: " + self . visibility . to_s +
i + " virtual: \n " + self . virtual . to_s +
i + " class_id: \n " + self . class_id . to_s
end
end
# @brief Describes a structure, class or union
# @attribute kind :struct, :class or :union
# @attribute id The name of the struct, class or union
# @attribute base_classes The base class declarations (an array of CPPBaseClass objects)
# @attribute body_decl An array or CPPUsingSpec, CPPFriendDecl, CPPTypedef, CPPEnumDeclaration, CPPStructDeclaration or CPPDeclaration objects
# "body_decl" forms the body of the class. It contains friend declarations, using specs, typedef's, enum's,
# nested struct's or method and member declarations.
class CPPStruct < CPPObject
attr_accessor :kind , :id , :base_classes , :body_decl
def_initializer :kind , :id , :base_classes , :body_decl
def to_s
self . kind . to_s + " " + self . id . to_s
end
def dump ( i )
l = i + self . kind . to_s + " : " + self . id . to_s + " \n "
l += ( self . base_classes || [ ] ) . collect { | b | i + " < " + b . to_s + " \n " } . join ( " " )
l += ( self . body_decl || [ ] ) . collect { | b | b . dump ( i + " " ) } . join ( " \n " )
end
end
# @param Describes a type derived with "__typeof"
# @attribute what The object from which the type is derived (a CPPQualifiedId)
class CPPTypeOf < CPPObject
attr_accessor :what
def_initializer :what
def to_s
" __typeof( " + what . to_s + " ) "
end
def dump ( i )
i + " CPPTypeOf \n " +
i + " what: " + self . what . to_s
end
end
# @param Describes an ellipsis inside a function argument list
class CPPEllipsis < CPPObject
def to_s
" ... "
end
def dump ( i )
i + " CPPEllipsis "
end
end
# @brief A general type definition
# @attribute concrete The concrete part of the type: a CPPPOD, CPPStruct, CPPEnum, CPPTypeof or CPPQualifiedId object)
# @attribute inner The "inner part": one of the CPPOuterType-derived classes or CPPQualifiedId
# @attribute init A string indicating the initialization expression
# If the concrete type is a class, struct, union, enum or typedef, a CPPQualifiedId is used for the
# attribute, describing the initial type (which can be complex already in the case of a typedef).
# The "inner" declarations add pointers, references, arrays of functions and finally the identifier.
# Without any further qualification, "inner" is a CPPQualifiedId object.
class CPPType < CPPObject
attr_accessor :concrete , :inner , :init
def_initializer :concrete , :inner , :init
def to_s
i = self . inner . to_s
s = self . concrete . to_s + " " + i
# nicen:
s . gsub ( / \ s+ / , " " ) . sub ( / ^ \ s* / , " " ) . sub ( / \ s*$ / , " " ) . gsub ( / \ ( / , " ( " ) . gsub ( / \ * / , " * " ) . gsub ( / & / , " & " )
end
def dump ( i )
i + " CPPType \n " +
i + " init: " + ( self . init ? self . init . to_s : " nil " ) + " \n " +
i + " concrete: \n " + ( self . concrete ? self . concrete . dump ( i + " " ) : i + " nil " ) + " \n " +
i + " inner: \n " + self . inner . dump ( i + " " )
end
end
# @brief A "using" instruction
# @attribute qid The qualified Id of the using specification
# @attribute visibility :default, :public, :private or :protected
class CPPUsingSpec < CPPObject
attr_accessor :qid , :visibility
def_initializer :qid , :visibility
def dump ( i )
i + " using [ " + self . visibility . to_s + " ]: " + self . qid . to_s
end
end
# @brief A typedef instruction
# @attribute type The declared type (a CPPType object, the inner name is the name of the defined type)
# @attribute visibility :default, :public, :private or :protected
class CPPTypedef < CPPObject
attr_accessor :type , :visibility
def_initializer :type , :visibility
def dump ( i )
i + " typedef [ " + self . visibility . to_s + " ]: " + self . type . to_s
end
end
# @brief A friend declaration
# @attribute decl An array of friend types (an array of CPPType objects)
class CPPFriendDecl < CPPObject
attr_accessor :decl
def_initializer :decl
def dump ( i )
self . decl . collect { | d | i + " friend: " + d . to_s } . join ( " \n " )
end
end
# @brief A type template argument (with an optional initializer)
2021-11-27 00:08:50 +01:00
# @attribute type The template argument (a type)
2017-02-21 20:32:40 +01:00
# @attribute def_type The default type (nil or a CPPType object)
class CPPClassTemplateArg < CPPObject
2021-11-27 00:08:50 +01:00
attr_accessor :type , :def_type
def_initializer :type , :def_type
2017-02-21 20:32:40 +01:00
def to_s
2021-11-27 00:08:50 +01:00
if self . def_type
self . type . to_s + " = " + self . def_type . to_s
else
self . type . to_s
end
2017-02-21 20:32:40 +01:00
end
end
# @brief A template declaration
# @attribute parts An array of CPPClassTemplateArg or CPPDirectTemplateArg objects
# CPPClassTemplateArg objects describe type arguments while CPPDirectTemplateArg objects
# describe value arguments (i.e. int).
class CPPTemplateDecl < CPPObject
attr_accessor :parts
def_initializer :parts
def to_s
( self . parts || [ ] ) . collect { | p | p . to_s } . join ( " , " )
end
end
# @brief An internal object, does not appear in the final parsed tree
class CPPAttr < CPPObject
attr_accessor :attr
def_initializer :attr
end
# @brief An struct/class/union declaration inside a namespace or class
# @attribute struct The CPPStruct object describing the class, struct or union
# @attribute template_decl nil or a CPPTemplateDecl object if the declaration is a template declaration
# @attribute visibility :default, :public, :private or :protected
class CPPStructDeclaration < CPPObject
attr_accessor :struct , :template_decl , :visibility
def_initializer :struct , :template_decl , :visibility
def dump ( i )
l = i + self . struct . kind . to_s + " _decl [ " + self . visibility . to_s + " ]: "
if self . template_decl
l += " template< " + self . template_decl . to_s + " > "
end
l += " \n "
l += self . struct . dump ( i + " " )
end
end
# @brief An enum declaration inside a namespace or class
# @attribute enum The CPPEnum object describing the enum
# @attribute visibility :default, :public, :private or :protected
class CPPEnumDeclaration < CPPObject
attr_accessor :enum , :visibility
def_initializer :enum , :visibility
def dump ( i )
i + " enum_decl [ " + self . visibility . to_s + " ]: \n " + self . enum . dump ( i + " " )
end
end
# @brief A declaration of either a function, a type, a member or a method
# @attribute type the declared type: a CPPType object
# @attribute template_decl nil or a CPPTemplateDecl object if the declaration is a template declaration
# @attribute visibility :default, :public, :private or :protected
# @attribute storage_class nil, :extern or :static
# @attribute virtual Is true for virtual methods
# @attribute inline Is true for inline declarations
class CPPDeclaration < CPPObject
attr_accessor :type , :template_decl , :visibility , :storage_class , :virtual , :inline
def_initializer :type , :template_decl , :visibility , :storage_class , :virtual , :inline
def dump ( i )
l = i
l += " decl [ " + self . visibility . to_s + " ]: "
if self . storage_class
l += self . storage_class . to_s + " "
end
if self . virtual
l += " virtual "
end
if self . inline
l += " inline "
end
if self . template_decl
l += " template< " + self . template_decl . to_s + " > "
end
if self . type . respond_to? ( :to_s )
l += self . type . to_s
else
l += self . type . dump ( i + " " )
end
l += " # " + self . myself . to_s
l
end
end
# @brief A namespace
# @attribute name The namespace name (a string)
# @attribute members The content of the namespace: an array of CPPTypedef, CPPNamespace (nested namespaces), CPPStructDeclaration, CPPEnumDeclaration or CPPDeclaration objects
class CPPNamespace < CPPObject
attr_accessor :name , :members
def_initializer :name , :members
def dump ( i )
l = i + " namespace #{ self . name } { \n "
l += ( self . members || [ ] ) . collect { | m | m . dump ( i + " " ) } . join ( " \n " )
l += i + " } "
end
end
# @brief Describes a single enum constant
# @attribute name The name of the enum constant
# @attribute init The initalizer (not parsed - just a string)
class CPPEnumSpec < CPPObject
attr_accessor :name , :init
def_initializer :name , :init
def to_s
self . name + ( self . init ? " = " + self . init : " " )
end
end
# @brief Describes an enum declaration
# @attribute name The name of the enum (a string)
# @attribute specs the enum members (an array of CPPEnumSpec objects)
class CPPEnum < CPPObject
2021-11-28 16:31:37 +01:00
attr_accessor :name , :specs , :is_class
def_initializer :name , :specs , :is_class
2017-02-21 20:32:40 +01:00
def to_s
" enum " + ( self . name || " " )
end
def dump ( i )
2021-11-28 16:31:37 +01:00
l = i + self . to_s + ( self . is_class ? " class " : " " ) + " { \n "
2017-02-21 20:32:40 +01:00
l += ( self . specs || [ ] ) . collect { | s | i + " " + s . to_s + " \n " } . join ( " " )
l += i + " } "
end
end
# @brief The root object of the declaration tree
# @attribute decls The content of the module: an array of CPPTypedef, CPPNamespace (nested namespaces), CPPStructDeclaration, CPPEnumDeclaration or CPPDeclaration objects
class CPPModule < CPPObject
attr_accessor :decls
def_initializer :decls
def dump
( self . decls || [ ] ) . collect { | d | d . dump ( " " ) } . join ( " \n " )
end
end