mirror of
https://github.com/KLayout/klayout.git
synced 2026-09-06 09:17:42 +02:00
Added scripts for Qt generation.
This commit is contained in:
@@ -0,0 +1,414 @@
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
require "cpp_classes.rb"
|
||||
require "cpp_parser_classes.rb"
|
||||
|
||||
grammar CPP
|
||||
|
||||
rule s
|
||||
[ \t\n\r]*
|
||||
end
|
||||
|
||||
rule sp
|
||||
[ \t\n\r]+
|
||||
end
|
||||
|
||||
rule string_const
|
||||
'"' ( [^\\"] / "\\" . )* '"'
|
||||
end
|
||||
|
||||
rule char_const
|
||||
"'" ( [^\\'] / "\\" . )* "'"
|
||||
end
|
||||
|
||||
rule numeric_const
|
||||
"-"? ( [0-9]+ ( "." [0-9]* )? / "." [0-9]+ ) ( [eE] "-"? [0-9]+ )?
|
||||
end
|
||||
|
||||
rule hex_const
|
||||
"0x" [0-9a-fA-F]+
|
||||
end
|
||||
|
||||
rule attribute_value
|
||||
"(" ( s ( "," s )? attribute_value )* s ")" / numeric_const / string_const / id
|
||||
end
|
||||
|
||||
rule a
|
||||
s ( "__attribute__" s attribute_value s / "__asm" s attribute_value s / "__extension__" s )*
|
||||
end
|
||||
|
||||
rule unary_op
|
||||
"~" / "!" / "-" / "*" / "&"
|
||||
end
|
||||
|
||||
rule bin_op_wo_gt
|
||||
"+=" / "++" / "+" / "->" / "-=" / "--" / "-" / "()" / "[]" / "&&" / "&=" / "&" / "||" / "|=" / "|" /
|
||||
"==" / "=" / "!=" / "*=" / "*" / "/=" / "/" / "%=" / "%" / "<=" / "<<=" / "<<" / "<" /
|
||||
"~=" / "^=" / "^" / "~=" / ">=" / ">>="
|
||||
end
|
||||
|
||||
rule bin_op
|
||||
bin_op_wo_gt / ">>" / ">"
|
||||
end
|
||||
|
||||
rule id
|
||||
"operator" s "," /
|
||||
"operator" s ( bin_op / unary_op / "," ) /
|
||||
"operator" sp [a-zA-Z\*\& \t\n\r]+ &( s "(" ) /
|
||||
"~"? [a-zA-Z_] [a-zA-Z_0-9]*
|
||||
end
|
||||
|
||||
rule template_arg_part_any
|
||||
block_wo_gt <PConst>
|
||||
end
|
||||
|
||||
rule template_arg_part
|
||||
qualified_id &( ( s ">" / "," ) ) / template_arg_part_any
|
||||
end
|
||||
|
||||
rule template_args
|
||||
template_arg_part ( s "," s template_arg_part )* <PTemplateArgs>
|
||||
end
|
||||
|
||||
rule id_with_template_args
|
||||
id:id taspec:( s "<" s ta:template_args s ">" )? <PId>
|
||||
end
|
||||
|
||||
rule qualified_id
|
||||
globalspec:( "::" s )? id_with_template_args ( s "::" id_with_template_args )* <PQualifiedId>
|
||||
end
|
||||
|
||||
rule int_type_attr
|
||||
"signed" ![a-zA-Z0-9_] / "unsigned" ![a-zA-Z0-9_] / "long" ( sp "long" )? ![a-zA-Z0-9_] / "short" ![a-zA-Z0-9_]
|
||||
end
|
||||
|
||||
rule int_type
|
||||
(
|
||||
( int_type_attr s )* "int" ![a-zA-Z0-9_] /
|
||||
int_type_attr ( s int_type_attr )* !"char" ( s "int" ![a-zA-Z0-9_] )?
|
||||
) <PIntType>
|
||||
end
|
||||
|
||||
rule char_type
|
||||
( "signed" sp / "unsigned" sp )? s !"int" "char" ![a-zA-Z0-9_] <PCharType>
|
||||
end
|
||||
|
||||
rule bool_type
|
||||
"bool" <PBoolType>
|
||||
end
|
||||
|
||||
rule void_type
|
||||
"void" <PVoidType>
|
||||
end
|
||||
|
||||
rule float_type
|
||||
( "long" sp )? ( "double" / "float" ) ![a-zA-Z0-9_] <PFloatType>
|
||||
end
|
||||
|
||||
rule enum_spec
|
||||
id:id initspec:( s "=" s init:block_wo_comma )? <PEnumSpec>
|
||||
end
|
||||
|
||||
rule enum_body
|
||||
enum_spec ( s "," s enum_spec )*
|
||||
end
|
||||
|
||||
rule enum_type
|
||||
"enum" ![a-zA-Z0-9_] a s id:id? bodyspec:( s "{" s body:enum_body s "}" )? <PEnumType>
|
||||
end
|
||||
|
||||
rule virtual_spec
|
||||
"virtual" <PVirtual>
|
||||
end
|
||||
|
||||
rule member_declaration_wo_semicolon
|
||||
template:( d:template_decl s )?
|
||||
attr:( ( "explicit" / "mutable" / storage_class / inline_spec / virtual_spec ) s )*
|
||||
t:type
|
||||
# type declaration ends with a } .. does not need a semicolon
|
||||
# (i.e. nested struct or enum)
|
||||
&{ |seq| seq[-1].text_value_ends_with_curly_brace }
|
||||
s
|
||||
( ":" s block_wo_curly_braces s )?
|
||||
a
|
||||
(
|
||||
"{" s block s "}" /
|
||||
";"?
|
||||
) <PDeclaration>
|
||||
end
|
||||
|
||||
rule member_declaration_w_semicolon
|
||||
template:( d:template_decl s )?
|
||||
attr:( ( "explicit" / "mutable" / storage_class / inline_spec / virtual_spec ) s )*
|
||||
t:type
|
||||
# opposite case (member_see declaration_wo_semicolon)
|
||||
# (i.e. nested struct or enum)
|
||||
!{ |seq| seq[-1].text_value_ends_with_curly_brace }
|
||||
s
|
||||
( ":" s block_wo_curly_braces s )?
|
||||
a
|
||||
(
|
||||
"{" s block s "}" /
|
||||
";"
|
||||
) <PDeclaration>
|
||||
end
|
||||
|
||||
rule member_declaration
|
||||
a ( member_declaration_wo_semicolon / member_declaration_w_semicolon )
|
||||
end
|
||||
|
||||
rule friend_decl
|
||||
a template:( d:template_decl s )? "friend" ![a-zA-Z0-9_] s t:member_declaration <PFriendDecl>
|
||||
end
|
||||
|
||||
rule class_struct_body_declarations
|
||||
( s ";" / s friend_decl / s using / s typedef / s !( "public" / "private" / "protected" ) member_declaration )*
|
||||
end
|
||||
|
||||
rule class_struct_body
|
||||
class_struct_body_declarations
|
||||
(
|
||||
s "public" s ":" d:class_struct_body_declarations <PPublicClassStructBodyDeclarations> /
|
||||
s "private" s ":" d:class_struct_body_declarations <PPrivateClassStructBodyDeclarations> /
|
||||
s "protected" s ":" d:class_struct_body_declarations <PProtectedClassStructBodyDeclarations>
|
||||
)*
|
||||
end
|
||||
|
||||
rule class_id
|
||||
# In order to easily distinguish between constructor methods without
|
||||
# a return type and class or typedef names we assume that all "name("
|
||||
# constructs are considered constructor names but "name (*func_ptr) ()" is not.
|
||||
qualified_id s !( "(" !( s "*" ) )
|
||||
end
|
||||
|
||||
rule typeof
|
||||
"__typeof" s "(" s qid:qualified_id s ")" <PTypeOf>
|
||||
end
|
||||
|
||||
rule base_class
|
||||
attr:( "public" ![a-zA-Z0-9_] s / "private" ![a-zA-Z0-9_] s / "protected" ![a-zA-Z0-9_] s / "virtual" ![a-zA-Z0-9_] s )* a cid:class_id <PBaseClass>
|
||||
end
|
||||
|
||||
rule base_classes
|
||||
base_class ( s "," s base_classes )?
|
||||
end
|
||||
|
||||
rule class_or_struct_type
|
||||
stype:( "union" ![a-zA-Z0-9_] / "struct" ![a-zA-Z0-9_] / "class" ![a-zA-Z0-9_] ) a idspec:( s id:class_id )? bcspec:( s ":" s bc:base_classes )? bodyspec:( s "{" s body:class_struct_body s "}" )? <PStructOrClassType>
|
||||
end
|
||||
|
||||
rule concrete_type
|
||||
( class_or_struct_type / enum_type / float_type / char_type / int_type / bool_type / void_type / typeof / class_id )?
|
||||
end
|
||||
|
||||
rule cv
|
||||
( "const" ![a-zA-Z0-9_] / "__const" ![a-zA-Z0-9_] / "volatile" ![a-zA-Z0-9_] / "__volatile" ![a-zA-Z0-9_] ) <PCV>
|
||||
end
|
||||
|
||||
rule pointer
|
||||
cvspec:( cv:cv s )? "*" itspec:( s it:inner_type )? <PPointer>
|
||||
end
|
||||
|
||||
rule reference
|
||||
cvspec:( cv:cv s )? "&" itspec:( s it:inner_type )? <PReference>
|
||||
end
|
||||
|
||||
rule array_spec
|
||||
"[" s block_wo_comma s "]" <PArraySpec>
|
||||
end
|
||||
|
||||
rule func_arg_part
|
||||
t:type_wo_comma !"..." <PFuncArgPart>
|
||||
end
|
||||
|
||||
rule ellipsis
|
||||
"..." <PEllipsis>
|
||||
end
|
||||
|
||||
rule func_args
|
||||
&")" /
|
||||
func_arg_part ( s "," s func_arg_part )* ( s "," s ellipsis )? /
|
||||
ellipsis
|
||||
end
|
||||
|
||||
rule func_spec
|
||||
"(" s fa:( a:func_args )? s ")" cvspec:( s cv:cv )? ( s "throw" s "(" s ( type_wo_comma s )? ")" )* a <PFuncSpec>
|
||||
end
|
||||
|
||||
rule member_pointer
|
||||
cspec:( qid:qualified_id s "::*" s ) itspec:( it:inner_type )? cvspec:( s cv:cv )? <PMemberPointer>
|
||||
end
|
||||
|
||||
rule inner_type_with_cv
|
||||
cvspec:cv s it:inner_type <PInnerTypeWithCV>
|
||||
end
|
||||
|
||||
rule inner_type
|
||||
it:(
|
||||
"(" s inner_type s ")" /
|
||||
inner_type_with_cv /
|
||||
pointer /
|
||||
reference /
|
||||
member_pointer /
|
||||
( "__restrict" ![a-zA-Z0-9_] s )? qualified_id
|
||||
)
|
||||
pfx:( s spec:( array_spec / func_spec ) )*
|
||||
<PInnerType>
|
||||
end
|
||||
|
||||
rule type
|
||||
cvspec:( cv:cv s )?
|
||||
a
|
||||
( "typename" ![a-zA-Z0-9_] s )?
|
||||
ct:concrete_type
|
||||
a
|
||||
il:( s t1:inner_type i1:(s "=" s is1:block_wo_comma)? tt:( s "," s t2:inner_type i2:(s "=" s is2:block_wo_comma)? )* )?
|
||||
# alternative initialization if only a concrete type is given:
|
||||
pi:( s "=" s is:block_wo_comma )?
|
||||
<PType>
|
||||
end
|
||||
|
||||
rule type_wo_comma
|
||||
cvspec:( cv:cv s )?
|
||||
a
|
||||
( "typename" ![a-zA-Z0-9_] s )?
|
||||
ct:concrete_type
|
||||
il:( s t:inner_type i:(s "=" s is:block_wo_comma)? )?
|
||||
# alternative initialization if only a concrete type is given:
|
||||
pi:( s "=" s is:block_wo_comma )?
|
||||
<PTypeWoComma>
|
||||
end
|
||||
|
||||
rule type_for_template
|
||||
cvspec:( cv:cv s )?
|
||||
a
|
||||
( "typename" ![a-zA-Z0-9_] s )?
|
||||
ct:concrete_type
|
||||
il:( s t:inner_type )?
|
||||
<PTypeForTemplate>
|
||||
end
|
||||
|
||||
rule storage_class
|
||||
( "static" ![a-zA-Z0-9_] / "extern" ![a-zA-Z0-9_] ( s '"C"' / s '"C++"' / s '"Pascal"' )? ) <PStorageClass>
|
||||
end
|
||||
|
||||
rule inline_spec
|
||||
"inline" ![a-zA-Z0-9_] <PInline>
|
||||
end
|
||||
|
||||
# parse over blocks as gracefully as possible ...
|
||||
rule block_atom_wo_gt
|
||||
"(" s block s ")" / "[" s block s "]" / "<" s block_wo_gt ( s "," s block_wo_gt )* s ">" /
|
||||
numeric_const / hex_const / string_const / char_const /
|
||||
id / unary_op / bin_op_wo_gt / "?" / "::" / "." / ":" / ";"
|
||||
end
|
||||
|
||||
rule block_wo_gt
|
||||
( s block_atom_wo_gt / s "{" s block s "}" )*
|
||||
end
|
||||
|
||||
# parse over blocks as gracefully as possible ...
|
||||
rule block_atom
|
||||
"(" s block s ")" / "[" s block s "]" / "<" s block_wo_gt ( s "," s block_wo_gt )* s ">" /
|
||||
numeric_const / hex_const / string_const / char_const /
|
||||
id / unary_op / bin_op / "?" / "::" / "." / ":"
|
||||
end
|
||||
|
||||
rule block
|
||||
( s block_atom / s ";" / s "," / s "{" s block s "}" )*
|
||||
end
|
||||
|
||||
rule block_wo_curly_braces
|
||||
( s block_atom / s "," )*
|
||||
end
|
||||
|
||||
rule block_wo_comma
|
||||
( s block_atom / s "{" s block s "}" )*
|
||||
end
|
||||
|
||||
rule using
|
||||
"using" ![a-zA-Z0-9_] ( s "namespace" )? ![a-zA-Z0-9_] s id:qualified_id a ";" <PUsing>
|
||||
end
|
||||
|
||||
rule typedef
|
||||
a "typedef" ![a-zA-Z0-9_] s t:type a ";" <PTypedef>
|
||||
end
|
||||
|
||||
rule template_decl_arg
|
||||
( "class" / "typename" ) ![a-zA-Z0-9_] s id:id dtspec:( s "=" s dt:type_for_template )? <PClassTemplateArg> /
|
||||
t:type_for_template initspec:( s "=" s init:block_wo_gt )? <PDirectTemplateArg>
|
||||
end
|
||||
|
||||
rule template_decl
|
||||
"template" s "<" s ( !">" template_decl_arg s ( "," s template_decl_arg )* )? s ">" <PTemplateDecl>
|
||||
end
|
||||
|
||||
rule declaration_w_semicolon
|
||||
template:( d:template_decl s )?
|
||||
template_member:( d_member:template_decl s )?
|
||||
attr:( ( storage_class / inline_spec ) s )*
|
||||
a
|
||||
t:type
|
||||
# type declaration ends with a } .. does not need a semicolon
|
||||
# (i.e. nested struct or enum)
|
||||
!{ |seq| seq[-1].text_value_ends_with_curly_brace }
|
||||
s ( ":" s block_wo_curly_braces s )?
|
||||
a
|
||||
(
|
||||
"{" s block s "}" /
|
||||
";"
|
||||
) <PDeclaration>
|
||||
end
|
||||
|
||||
rule declaration_wo_semicolon
|
||||
template:( d:template_decl s )?
|
||||
attr:( ( storage_class / inline_spec ) s )*
|
||||
a
|
||||
t:type
|
||||
# opposite case (see declaration_wo_semicolon)
|
||||
# (i.e. nested struct or enum)
|
||||
&{ |seq| seq[-1].text_value_ends_with_curly_brace }
|
||||
s ( ":" s block_wo_curly_braces s )?
|
||||
a
|
||||
(
|
||||
"{" s block s "}" /
|
||||
";"?
|
||||
) <PDeclaration>
|
||||
end
|
||||
|
||||
rule declaration
|
||||
declaration_w_semicolon / declaration_wo_semicolon
|
||||
end
|
||||
|
||||
rule namespace
|
||||
"namespace" ![a-zA-Z0-9_] s n:id
|
||||
a "{" decls:( a ( ";" / using / typedef / namespace / declaration ) )* s "}" <PNamespace>
|
||||
end
|
||||
|
||||
rule extern_decl
|
||||
"extern" s n:( '"C"' / '"C++"' / '"Pascal"' ) s
|
||||
a "{" decls:( a ( ";" / typedef / namespace / extern_decl / declaration ) )* s "}" <PExternBlock>
|
||||
end
|
||||
|
||||
rule module
|
||||
( a ( ";" / using / typedef / namespace / extern_decl / declaration ) )* s <PModule>
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,654 @@
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
|
||||
attr_accessor :inner, :args, :cv
|
||||
def_initializer :inner, :args, :cv
|
||||
|
||||
def to_s
|
||||
a = self.args
|
||||
a ||= []
|
||||
if !a.is_a?(Array)
|
||||
a = [a]
|
||||
end
|
||||
self.inner.to_s + " (" + a.join(", ") + ")" + (self.cv ? " " + self.cv.to_s : "")
|
||||
end
|
||||
|
||||
def dump(i)
|
||||
i + "CPPFunc\n" + i + " inner:\n" + self.inner.dump(i + " ") + "\n" +
|
||||
i + " cv: " + self.cv.to_s + "\n" +
|
||||
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)
|
||||
# @attribute id The name of the argument (a string)
|
||||
# @attribute def_type The default type (nil or a CPPType object)
|
||||
class CPPClassTemplateArg < CPPObject
|
||||
|
||||
attr_accessor :id, :def_type
|
||||
def_initializer :id, :def_type
|
||||
|
||||
def to_s
|
||||
self.id + (self.def_type ? ("=" + self.def_type.to_s) : "")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# @brief A value template argument (with an optional initializer)
|
||||
# @attribute type A CPPType object describing the type
|
||||
# @attribute def_expr The initializer expression (a string) or nil if no initializer is given
|
||||
class CPPDirectTemplateArg < CPPObject
|
||||
|
||||
attr_accessor :type, :def_expr
|
||||
def_initializer :type, :def_expr
|
||||
|
||||
def to_s
|
||||
self.type.to_s + (self.def_expr ? ("=" + self.def_expr.to_s) : "")
|
||||
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
|
||||
|
||||
attr_accessor :name, :specs
|
||||
def_initializer :name, :specs
|
||||
|
||||
def to_s
|
||||
"enum " + (self.name || "")
|
||||
end
|
||||
|
||||
def dump(i)
|
||||
l = i + self.to_s + " {\n"
|
||||
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
|
||||
|
||||
@@ -0,0 +1,474 @@
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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 Treetop::Runtime::SyntaxNode
|
||||
|
||||
# An alias which can be used inside a derived cpp implementation
|
||||
# The default implementation collects all objects emitted by the subnodes.
|
||||
def get_cpp
|
||||
a = elements && elements.collect { |e| e.cpp }.select { |e| e }.flatten
|
||||
(a && !a.empty?) ? a : nil
|
||||
end
|
||||
|
||||
# Returns the CPP objects emitted by this node.
|
||||
# This method delivers CPP objects or arrays of CPP objects.
|
||||
def cpp
|
||||
get_cpp
|
||||
end
|
||||
|
||||
# Returns the single CPP object or nil
|
||||
def cpp_reduced
|
||||
a = self.cpp
|
||||
if a.is_a?(Array)
|
||||
a.size == 1 || raise("Internal error: more than one syntax tree node")
|
||||
a = a[0]
|
||||
end
|
||||
a
|
||||
end
|
||||
|
||||
# Note: this method is required because curly braces cannot be put
|
||||
# into parser conditions (treetop syntax flaw?)
|
||||
def text_value_ends_with_curly_brace
|
||||
text_value =~ /\}$/
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# These are a couple of emitter extensions to SyntaxNode which produce the definition syntax tree
|
||||
# through the "cpp" method:
|
||||
|
||||
module PTypeOf
|
||||
def cpp
|
||||
CPPTypeOf::new(qid.cpp)
|
||||
end
|
||||
end
|
||||
|
||||
def extract_signed(t)
|
||||
if t =~ /unsigned/
|
||||
:unsigned
|
||||
elsif t =~ /signed/
|
||||
:signed
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def extract_length(t)
|
||||
if t =~ /long long/
|
||||
:longlong
|
||||
elsif t =~ /long/
|
||||
:long
|
||||
elsif t =~ /short/
|
||||
:short
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
module PIntType
|
||||
def cpp
|
||||
CPPPOD::new(extract_signed(text_value), extract_length(text_value), :int)
|
||||
end
|
||||
end
|
||||
|
||||
module PCharType
|
||||
def cpp
|
||||
CPPPOD::new(extract_signed(text_value), nil, :char)
|
||||
end
|
||||
end
|
||||
|
||||
module PBoolType
|
||||
def cpp
|
||||
CPPPOD::new(nil, nil, :bool)
|
||||
end
|
||||
end
|
||||
|
||||
module PSpecialType
|
||||
def cpp
|
||||
# the special type produces an ID
|
||||
CPPQualifiedId::new(false, [ CPPId::new(id.text_value, nil) ])
|
||||
end
|
||||
end
|
||||
|
||||
module PFloatType
|
||||
def cpp
|
||||
kind = text_value =~ /double/ ? :double : :float
|
||||
CPPPOD::new(nil, extract_length(text_value), kind)
|
||||
end
|
||||
end
|
||||
|
||||
module PVoidType
|
||||
def cpp
|
||||
CPPPOD::new(nil, nil, :void)
|
||||
end
|
||||
end
|
||||
|
||||
module PEnumSpec
|
||||
def cpp
|
||||
CPPEnumSpec::new(id.text_value, initspec.nonterminal? ? initspec.init.text_value : nil)
|
||||
end
|
||||
end
|
||||
|
||||
module PEnumType
|
||||
def cpp
|
||||
name = id ? id.text_value : nil
|
||||
specs = bodyspec.nonterminal? ? bodyspec.body.cpp : nil
|
||||
CPPEnum::new(name, specs)
|
||||
end
|
||||
end
|
||||
|
||||
module PConst
|
||||
def cpp
|
||||
CPPConst::new(text_value)
|
||||
end
|
||||
end
|
||||
|
||||
module PTemplateArgs
|
||||
def cpp
|
||||
decl = self.get_cpp
|
||||
decl ? CPPTemplateArgs::new(decl) : nil
|
||||
end
|
||||
end
|
||||
|
||||
module PId
|
||||
def cpp
|
||||
CPPId::new(id.text_value, taspec.nonterminal? ? taspec.ta.cpp_reduced : nil)
|
||||
end
|
||||
end
|
||||
|
||||
module PQualifiedId
|
||||
def cpp
|
||||
CPPQualifiedId::new(globalspec.nonterminal?, self.get_cpp)
|
||||
end
|
||||
end
|
||||
|
||||
module PBaseClass
|
||||
def cpp
|
||||
visibility = nil
|
||||
virtual = false
|
||||
at = attr.text_value
|
||||
if at =~ /private/
|
||||
visibility = :private
|
||||
elsif at =~ /public/
|
||||
visibility = :public
|
||||
elsif at =~ /protected/
|
||||
visibility = :protected
|
||||
end
|
||||
if at =~ /virtual/
|
||||
virtual = true
|
||||
end
|
||||
CPPBaseClass::new(visibility, virtual, cid.cpp_reduced)
|
||||
end
|
||||
end
|
||||
|
||||
module PStructOrClassType
|
||||
|
||||
def cpp
|
||||
|
||||
kind = :class
|
||||
if stype.text_value == "struct"
|
||||
kind = :struct
|
||||
elsif stype.text_value == "union"
|
||||
kind = :union
|
||||
end
|
||||
|
||||
id = idspec.nonterminal? ? idspec.id.cpp_reduced : nil
|
||||
base_classes = bcspec.nonterminal? ? bcspec.bc.cpp : nil
|
||||
body_decl = bodyspec.nonterminal? ? bodyspec.body.cpp : nil
|
||||
|
||||
CPPStruct::new(kind, id, base_classes, body_decl)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module PCV
|
||||
def to_symbol
|
||||
return self.text_value == "const" ? :const : :volatile
|
||||
end
|
||||
end
|
||||
|
||||
module PFriendDecl
|
||||
def cpp
|
||||
CPPFriendDecl::new(t.cpp)
|
||||
end
|
||||
end
|
||||
|
||||
module PPointer
|
||||
def cpp
|
||||
CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, CPPPointer::new(itspec.nonterminal? ? itspec.it.cpp_reduced : CPPAnonymousId::new))
|
||||
end
|
||||
end
|
||||
|
||||
module PReference
|
||||
def cpp
|
||||
CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, CPPReference::new(itspec.nonterminal? ? itspec.it.cpp_reduced : CPPAnonymousId::new))
|
||||
end
|
||||
end
|
||||
|
||||
module PMemberPointer
|
||||
def cpp
|
||||
CPPMemberPointer::new(cspec.qid.cpp, itspec.nonterminal? ? itspec.it.cpp_reduced : CPPAnonymousId::new, cvspec.nonterminal? && cvspec.cv.to_symbol)
|
||||
end
|
||||
end
|
||||
|
||||
module PArraySpec
|
||||
def cpp
|
||||
CPPArray::new(nil)
|
||||
end
|
||||
end
|
||||
|
||||
module PFuncArgPart
|
||||
def cpp
|
||||
t.cpp_reduced
|
||||
end
|
||||
end
|
||||
|
||||
module PFuncSpec
|
||||
def cpp
|
||||
CPPFunc::new(nil, (fa.nonterminal? && fa.text_value != "void") ? (fa.a.cpp || []) : [], cvspec.nonterminal? && cvspec.cv.to_symbol)
|
||||
end
|
||||
end
|
||||
|
||||
module PInnerTypeWithCV
|
||||
def cpp
|
||||
CPPCV::wrap(cvspec.to_symbol, it.cpp_reduced)
|
||||
end
|
||||
end
|
||||
|
||||
module PInnerType
|
||||
def cpp
|
||||
if pfx.nonterminal?
|
||||
pfx.elements.inject(it.cpp_reduced) do |r,e|
|
||||
ee = e.spec.cpp_reduced
|
||||
ee.inner = r
|
||||
ee
|
||||
end
|
||||
else
|
||||
it.cpp
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PStorageClass
|
||||
def cpp
|
||||
if text_value =~ /^static/
|
||||
return CPPAttr::new(:static)
|
||||
elsif text_value =~ /^extern/
|
||||
return CPPAttr::new(:extern)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PVirtual
|
||||
def cpp
|
||||
return CPPAttr::new(:virtual)
|
||||
end
|
||||
end
|
||||
|
||||
module PInline
|
||||
def cpp
|
||||
return CPPAttr::new(:inline)
|
||||
end
|
||||
end
|
||||
|
||||
module PType
|
||||
|
||||
def cpp
|
||||
# This is the class/struct/union/enum declaration if there is one
|
||||
d = ct.cpp
|
||||
if d.is_a?(Array)
|
||||
r = d.select { |i| i.is_a?(CPPStruct) || i.is_a?(CPPEnum) }
|
||||
elsif d.is_a?(CPPStruct) || d.is_a?(CPPEnum)
|
||||
r = [d]
|
||||
else
|
||||
r = []
|
||||
end
|
||||
# Create each declaration
|
||||
ot = CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, ct.cpp_reduced)
|
||||
if il.nonterminal?
|
||||
r << CPPType::new(ot, il.t1.cpp_reduced, il.i1.nonterminal? ? il.i1.is1.text_value : nil)
|
||||
il.tt.elements.each do |t|
|
||||
r << CPPType::new(ot, t.t2.cpp_reduced, t.i2.nonterminal? ? t.i2.is2.text_value : nil)
|
||||
end
|
||||
else
|
||||
r << CPPType::new(ot, CPPAnonymousId::new, pi.nonterminal? ? pi.is.text_value : nil)
|
||||
end
|
||||
r
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module PEllipsis
|
||||
def cpp
|
||||
CPPEllipsis::new
|
||||
end
|
||||
end
|
||||
|
||||
module PTypeWoComma
|
||||
def cpp
|
||||
ot = CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, ct.cpp_reduced)
|
||||
if il.nonterminal?
|
||||
CPPType::new(ot, il.t.cpp_reduced, il.i.nonterminal? ? il.i.is.text_value : nil)
|
||||
else
|
||||
CPPType::new(ot, CPPAnonymousId::new, pi.nonterminal? ? pi.is.text_value : nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PTypeForTemplate
|
||||
def cpp
|
||||
ot = CPPCV::wrap(cvspec.nonterminal? && cvspec.cv.to_symbol, ct.cpp_reduced)
|
||||
CPPType::new(ot, il.nonterminal? ? il.t.cpp_reduced : CPPAnonymousId::new, nil)
|
||||
end
|
||||
end
|
||||
|
||||
module PUsing
|
||||
def cpp
|
||||
CPPUsingSpec::new(id.cpp_reduced, :default)
|
||||
end
|
||||
end
|
||||
|
||||
module PTypedef
|
||||
def cpp
|
||||
t.cpp.collect do |d|
|
||||
if d.is_a?(CPPStruct)
|
||||
CPPStructDeclaration::new(d, nil, :default)
|
||||
elsif d.is_a?(CPPEnum)
|
||||
CPPEnumDeclaration::new(d, :default)
|
||||
else
|
||||
CPPTypedef::new(d, :default)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PPrivateClassStructBodyDeclarations
|
||||
def cpp
|
||||
decl = d.cpp
|
||||
decl && decl.collect do |d|
|
||||
if d.respond_to?(:visibility)
|
||||
d.visibility = :private
|
||||
end
|
||||
d
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PProtectedClassStructBodyDeclarations
|
||||
def cpp
|
||||
decl = d.cpp
|
||||
decl && decl.collect do |d|
|
||||
if d.respond_to?(:visibility)
|
||||
d.visibility = :protected
|
||||
end
|
||||
d
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PPublicClassStructBodyDeclarations
|
||||
def cpp
|
||||
decl = d.cpp
|
||||
decl && decl.collect do |d|
|
||||
if d.respond_to?(:visibility)
|
||||
d.visibility = :public
|
||||
end
|
||||
d
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PTemplateDecl
|
||||
def cpp
|
||||
CPPTemplateDecl::new(self.get_cpp)
|
||||
end
|
||||
end
|
||||
|
||||
module PClassTemplateArg
|
||||
def cpp
|
||||
CPPClassTemplateArg::new(id.text_value, dtspec.nonterminal? ? dtspec.cpp : nil)
|
||||
end
|
||||
end
|
||||
|
||||
module PDirectTemplateArg
|
||||
def cpp
|
||||
CPPDirectTemplateArg::new(t.cpp, initspec.nonterminal? ? initspec.text_value : nil)
|
||||
end
|
||||
end
|
||||
|
||||
module PDeclaration
|
||||
def cpp
|
||||
td = nil
|
||||
if template.nonterminal?
|
||||
td = template.d.cpp
|
||||
end
|
||||
storage_class = nil
|
||||
virtual = nil
|
||||
inline = nil
|
||||
if attr.nonterminal? && attr.cpp
|
||||
attr.cpp.each do |d|
|
||||
if d.attr == :virtual
|
||||
virtual = true
|
||||
elsif d.attr == :inline
|
||||
inline = true
|
||||
elsif d.attr == :static
|
||||
storage_class = :static
|
||||
elsif d.attr == :extern
|
||||
storage_class = :extern
|
||||
end
|
||||
end
|
||||
end
|
||||
# TODO: abstract declaration determination should be based on initializers on the
|
||||
# inner types
|
||||
t.cpp.collect do |d|
|
||||
if d.is_a?(CPPStruct)
|
||||
CPPStructDeclaration::new(d, td, :default)
|
||||
elsif d.is_a?(CPPEnum)
|
||||
CPPEnumDeclaration::new(d, :default)
|
||||
else
|
||||
CPPDeclaration::new(d, td, :default, storage_class, virtual, inline)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PExternBlock
|
||||
def cpp
|
||||
self.get_cpp.collect do |d|
|
||||
if d.is_a?(CPPDeclaration)
|
||||
d.storage_class = :extern
|
||||
end
|
||||
d
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module PNamespace
|
||||
def cpp
|
||||
CPPNamespace::new(n.text_value, decls.cpp || [])
|
||||
end
|
||||
end
|
||||
|
||||
module PModule
|
||||
def cpp
|
||||
CPPModule::new(self.get_cpp)
|
||||
end
|
||||
end
|
||||
Executable
+51
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
$:.push(File.dirname($0))
|
||||
|
||||
require 'oj'
|
||||
require 'cpp_classes.rb'
|
||||
require 'reader_ext.rb'
|
||||
|
||||
input_file = "all.db"
|
||||
conf_file = "mkqtdecl.conf"
|
||||
cls_list = nil
|
||||
$gen_dir = "generated"
|
||||
|
||||
while ARGV.size > 0
|
||||
o = ARGV.shift
|
||||
if o == "-i"
|
||||
input_file = ARGV.shift
|
||||
else
|
||||
raise("Invalid option #{o} - usage is 'dump.rb -i all.db'")
|
||||
end
|
||||
end
|
||||
|
||||
File.open(input_file, "r") do |file|
|
||||
|
||||
json = file.read
|
||||
|
||||
@root = Oj.load(json)
|
||||
puts "Reading done."
|
||||
|
||||
puts @root.dump
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# A helper script to detect ambiguous methods
|
||||
|
||||
# run with
|
||||
# klayout -r mkqtdecl_extract_ambigous_methods.rb -z s
|
||||
|
||||
events = {}
|
||||
|
||||
classes = {}
|
||||
RBA::Class::each_class do |cls|
|
||||
classes[cls.name] = true
|
||||
end
|
||||
|
||||
RBA::Class::each_class do |cls|
|
||||
|
||||
tc = {
|
||||
RBA::ArgType.t_void => "",
|
||||
RBA::ArgType.t_bool => "b",
|
||||
RBA::ArgType.t_char => "i",
|
||||
RBA::ArgType.t_schar => "i",
|
||||
RBA::ArgType.t_uchar => "i",
|
||||
RBA::ArgType.t_short => "i",
|
||||
RBA::ArgType.t_ushort => "i",
|
||||
RBA::ArgType.t_int => "i",
|
||||
RBA::ArgType.t_uint => "i",
|
||||
RBA::ArgType.t_long => "i",
|
||||
RBA::ArgType.t_ulong => "i",
|
||||
RBA::ArgType.t_longlong => "i",
|
||||
RBA::ArgType.t_ulonglong => "i",
|
||||
RBA::ArgType.t_double => "d",
|
||||
RBA::ArgType.t_float => "d",
|
||||
RBA::ArgType.t_var => "v",
|
||||
RBA::ArgType.t_string => "s",
|
||||
RBA::ArgType.t_qstring => "s",
|
||||
RBA::ArgType.t_string_ccptr => "s",
|
||||
}
|
||||
|
||||
uc = {
|
||||
RBA::ArgType.t_void => "",
|
||||
RBA::ArgType.t_bool => "b",
|
||||
RBA::ArgType.t_char => "c",
|
||||
RBA::ArgType.t_schar => "c",
|
||||
RBA::ArgType.t_uchar => "uc",
|
||||
RBA::ArgType.t_short => "s",
|
||||
RBA::ArgType.t_ushort => "us",
|
||||
RBA::ArgType.t_int => "i",
|
||||
RBA::ArgType.t_uint => "ui",
|
||||
RBA::ArgType.t_long => "l",
|
||||
RBA::ArgType.t_ulong => "ul",
|
||||
RBA::ArgType.t_longlong => "w",
|
||||
RBA::ArgType.t_ulonglong => "uw",
|
||||
RBA::ArgType.t_double => "d",
|
||||
RBA::ArgType.t_float => "f",
|
||||
RBA::ArgType.t_var => "v",
|
||||
RBA::ArgType.t_string => "s",
|
||||
RBA::ArgType.t_qstring => "qs",
|
||||
RBA::ArgType.t_string_ccptr => "t",
|
||||
}
|
||||
|
||||
if cls.name =~ /_Native$/ || !classes[cls.name + "_Native"]
|
||||
|
||||
m = {}
|
||||
cls.each_method do |meth|
|
||||
m[meth.name] ||= {}
|
||||
csig = ""
|
||||
if meth.is_static?
|
||||
csig += "s"
|
||||
end
|
||||
if meth.is_const?
|
||||
csig += "c"
|
||||
end
|
||||
if csig != ""
|
||||
csig += "#"
|
||||
end
|
||||
meth.each_argument do |a|
|
||||
if a.is_ptr? || a.is_cptr?
|
||||
csig += "p"
|
||||
end
|
||||
if a.type == RBA::ArgType::t_vector
|
||||
csig += "a"
|
||||
csig += tc[a.inner.type].to_s
|
||||
elsif a.type == RBA::ArgType::t_object || a.type == RBA::ArgType::t_object_new
|
||||
csig += "x"
|
||||
csig += a.cls.name
|
||||
else
|
||||
csig += tc[a.type]
|
||||
end
|
||||
end
|
||||
((m[meth.name] ||= {})[csig] ||= []).push(meth)
|
||||
end
|
||||
|
||||
m.each do |n,cs|
|
||||
cs.each do |csig,m|
|
||||
if m.size > 1
|
||||
puts "Ambigous: #{cls.name}::#{n}_#{csig}"
|
||||
usigs = []
|
||||
m.each do |mm|
|
||||
usig = ""
|
||||
mm.each_argument do |a|
|
||||
if a.is_ptr? || a.is_cptr?
|
||||
usig += "p"
|
||||
end
|
||||
if a.type == RBA::ArgType::t_vector
|
||||
usig += "a"
|
||||
usig += uc[a.inner.type].to_s
|
||||
elsif a.type == RBA::ArgType::t_object || a.type == RBA::ArgType::t_object_new
|
||||
usig += "x"
|
||||
usig += a.cls.name
|
||||
else
|
||||
usig += uc[a.type]
|
||||
end
|
||||
end
|
||||
usigs.push(usig)
|
||||
end
|
||||
puts "-> #{usigs.join(',')}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# A helper script to detect non-const pointers
|
||||
# (those indicate ownership issues).
|
||||
|
||||
# run with
|
||||
# klayout -r mkqtdecl_extract_nc_pointers.rb -z s
|
||||
|
||||
events = {}
|
||||
|
||||
classes = {}
|
||||
RBA::Class::each_class do |cls|
|
||||
classes[cls.name] = true
|
||||
end
|
||||
|
||||
RBA::Class::each_class do |cls|
|
||||
|
||||
uc = {
|
||||
RBA::ArgType.t_void => "",
|
||||
RBA::ArgType.t_bool => "b",
|
||||
RBA::ArgType.t_char => "c",
|
||||
RBA::ArgType.t_schar => "c",
|
||||
RBA::ArgType.t_uchar => "uc",
|
||||
RBA::ArgType.t_short => "s",
|
||||
RBA::ArgType.t_ushort => "us",
|
||||
RBA::ArgType.t_int => "i",
|
||||
RBA::ArgType.t_uint => "ui",
|
||||
RBA::ArgType.t_long => "l",
|
||||
RBA::ArgType.t_ulong => "ul",
|
||||
RBA::ArgType.t_longlong => "w",
|
||||
RBA::ArgType.t_ulonglong => "uw",
|
||||
RBA::ArgType.t_double => "d",
|
||||
RBA::ArgType.t_float => "f",
|
||||
RBA::ArgType.t_var => "v",
|
||||
RBA::ArgType.t_string => "s",
|
||||
RBA::ArgType.t_qstring => "qs",
|
||||
RBA::ArgType.t_string_ccptr => "t",
|
||||
}
|
||||
|
||||
if cls.name =~ /_Native$/ || !classes[cls.name + "_Native"]
|
||||
|
||||
m = {}
|
||||
cls.each_method do |meth|
|
||||
m[meth.name] ||= {}
|
||||
has_ptr = false
|
||||
has_int = false
|
||||
csig = ""
|
||||
if meth.is_static?
|
||||
csig += "s"
|
||||
end
|
||||
if meth.is_const?
|
||||
csig += "c"
|
||||
end
|
||||
if csig != ""
|
||||
csig += "#"
|
||||
end
|
||||
meth.each_argument do |a|
|
||||
if a.is_ptr? || a.is_cptr?
|
||||
has_ptr = true
|
||||
csig += "p"
|
||||
end
|
||||
if a.type == RBA::ArgType::t_vector
|
||||
csig += "a"
|
||||
c = uc[a.inner.type].to_s
|
||||
csig += c
|
||||
elsif a.type == RBA::ArgType::t_object || a.type == RBA::ArgType::t_object_new
|
||||
csig += "x"
|
||||
csig += a.cls.name
|
||||
else
|
||||
c = uc[a.type]
|
||||
if c == "i" || c == "ui" || c == "l" || c == "ul"
|
||||
has_int = true
|
||||
end
|
||||
csig += c
|
||||
end
|
||||
end
|
||||
if has_ptr && has_int
|
||||
puts "#{cls.name}::#{meth.name}_#{csig}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# A helper script to detect potential factory methods
|
||||
|
||||
# run with
|
||||
# klayout -r mkqtdecl_extract_potential_factories.rb -z s
|
||||
|
||||
events = {}
|
||||
|
||||
RBA::Class::each_class do |cls|
|
||||
|
||||
if cls.name =~ /_Native$/
|
||||
cls.each_method do |meth|
|
||||
if meth.ret_type.is_ptr?
|
||||
if meth.name =~ /create/i || meth.name =~ /make/i || meth.name =~ /build/i
|
||||
puts "#{cls.name}::#{meth.name} -> #{meth.ret_type.to_s}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# A helper script to create or update the .properties configuration file.
|
||||
# This file will specify the methods that will be turned into properties
|
||||
# with a getter/setter pair or single getter/setter function.
|
||||
|
||||
# run with
|
||||
# klayout -r mkqtdecl_extract_props.rb -b >mkqtdecl.properties
|
||||
|
||||
classes = {}
|
||||
RBA::Class::each_class do |cls|
|
||||
classes[cls.name] = true
|
||||
end
|
||||
|
||||
puts "# Properties from Qt meta objects:"
|
||||
|
||||
setters_sig = {}
|
||||
getters_sig = {}
|
||||
|
||||
RBA::Class::each_class do |cls|
|
||||
|
||||
if cls.name =~ /^Q/ && (cls.name =~ /_Native$/ || !classes[cls.name + "_Native"])
|
||||
|
||||
b = cls.base
|
||||
while b && b.name != "QObject_Native"
|
||||
b = b.base
|
||||
end
|
||||
|
||||
if b
|
||||
|
||||
mo = eval("RBA::#{cls.name}.staticMetaObject")
|
||||
|
||||
c = cls.name.sub(/_Native$/, "")
|
||||
|
||||
valid_sig = {}
|
||||
(0..(mo.propertyCount-1)).each do |i|
|
||||
pr = mo.property(i)
|
||||
ucname = pr.name[0..0].upcase + pr.name[1..-1]
|
||||
if pr.isReadable
|
||||
puts "property_reader(\"#{c}\", /::(#{pr.name}|is#{ucname}|has#{ucname})\\s*\\(/, \"#{pr.name}\")"
|
||||
getters_sig["#{cls.name}##{pr.name}"] = true
|
||||
getters_sig["#{cls.name}#is#{ucname}"] = true
|
||||
getters_sig["#{cls.name}#has#{ucname}"] = true
|
||||
end
|
||||
if pr.isWritable
|
||||
puts "property_writer(\"#{c}\", /::set#{ucname}\\s*\\(/, \"#{pr.name}\")"
|
||||
setters_sig["#{cls.name}#set#{ucname}"] = true
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
puts ""
|
||||
puts "# Synthetic properties"
|
||||
|
||||
# strip const and references from types
|
||||
def normalize_type(s)
|
||||
if s =~ /^const\s+(.*)$/
|
||||
s = $1
|
||||
end
|
||||
if s =~ /^(.*?)\s*&/
|
||||
s = $1
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
RBA::Class::each_class do |cls|
|
||||
|
||||
if cls.name =~ /^Q/ && (cls.name =~ /_Native$/ || !classes[cls.name + "_Native"])
|
||||
|
||||
# make all methods into properties with the following signatures
|
||||
# setX(x) + x() -> "setX|x=" + ":x"
|
||||
# setX(x) + isX() -> "setX|x=" + "isX|:x"
|
||||
# setX(x) + hasX() -> "setX|x=" + "hasX|:x"
|
||||
#
|
||||
|
||||
getters = {}
|
||||
setters = {}
|
||||
|
||||
c = cls
|
||||
while c != nil
|
||||
|
||||
c.each_method do |m|
|
||||
|
||||
is_setter = false
|
||||
is_getter = false
|
||||
m.each_overload do |ov|
|
||||
is_setter ||= setters_sig["#{c.name}##{ov.name}"]
|
||||
is_getter ||= getters_sig["#{c.name}##{ov.name}"]
|
||||
end
|
||||
|
||||
if ! is_setter && m.accepts_num_args(1) && m.ret_type.to_s == "void"
|
||||
m.each_overload do |ov|
|
||||
if ov.name =~ /^set([A-Z])(\w*)$/
|
||||
pn = $1.downcase + $2
|
||||
setters[pn] ||= [ ov, c, m ]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if ! is_getter && m.accepts_num_args(0)
|
||||
m.each_overload do |ov|
|
||||
if ov.name =~ /^is([A-Z])(\w*)$/ || ov.name =~ /^has([A-Z])(\w*)$/ || ov.name =~ /^([a-z])(\w*)$/
|
||||
pn = $1.downcase + $2
|
||||
getters[pn] ||= [ ov, c, m ]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
c = c.base
|
||||
|
||||
end
|
||||
|
||||
setters.keys.sort.each do |pn|
|
||||
|
||||
s = setters[pn]
|
||||
g = getters[pn]
|
||||
|
||||
if g && (s[1] == cls || g[1] == cls)
|
||||
|
||||
a = nil
|
||||
s[2].each_argument { |aa| a ||= aa }
|
||||
setter_type = normalize_type(a.to_s)
|
||||
getter_type = normalize_type(g[2].ret_type.to_s)
|
||||
|
||||
if setter_type == getter_type
|
||||
puts "# Property #{pn} (#{setter_type})"
|
||||
gc = g[1].name.sub(/_Native$/, "")
|
||||
sc = s[1].name.sub(/_Native$/, "")
|
||||
puts "property_reader(\"#{gc}\", /::#{g[0].name}\\s*\\(/, \"#{pn}\")"
|
||||
puts "property_writer(\"#{sc}\", /::#{s[0].name}\\s*\\(/, \"#{pn}\")"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# A helper script to extract the signals from the Qt declarations
|
||||
# It can be used to write the .events configuration file which will
|
||||
# declare the signals of objects.
|
||||
|
||||
# run with
|
||||
# klayout -r mkqtdecl_extract_signals.rb -z >mkqtdecl.events
|
||||
|
||||
classes = {}
|
||||
RBA::Class::each_class do |cls|
|
||||
classes[cls.name] = true
|
||||
end
|
||||
|
||||
RBA::Class::each_class do |cls|
|
||||
|
||||
if cls.name =~ /^Q/ && (cls.name =~ /_Native$/ || !classes[cls.name + "_Native"])
|
||||
|
||||
b = cls.base
|
||||
while b && b.name != "QObject_Native"
|
||||
b = b.base
|
||||
end
|
||||
|
||||
if b
|
||||
|
||||
mo = eval("RBA::#{cls.name}.staticMetaObject")
|
||||
|
||||
c = cls.name.sub(/_Native/, "")
|
||||
|
||||
valid_sig = {}
|
||||
(0..(mo.methodCount-1)).each do |i|
|
||||
mm = mo.method(i)
|
||||
if mm.methodType == RBA::QMetaMethod::Signal
|
||||
n = mm.methodSignature.sub(/\(.*/, "")
|
||||
s = mm.parameterTypes.join(", ")
|
||||
valid_sig[n] ||= []
|
||||
found = false
|
||||
valid_sig[n] = valid_sig[n].select do |vs|
|
||||
ret = true
|
||||
if s.index(vs) == 0
|
||||
ret = false
|
||||
elsif vs.index(s) == 0
|
||||
found = true
|
||||
end
|
||||
ret
|
||||
end
|
||||
if !found
|
||||
valid_sig[n].push(s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
valid_sig.each do |n,ss|
|
||||
ss.each do |s|
|
||||
match = "::#{n}\\s*\\("
|
||||
renamed = nil
|
||||
aliased = nil
|
||||
if c == "QTabWidget"
|
||||
if n == "currentChanged" && s =~ /QWidget/
|
||||
match += ".*QWidget"
|
||||
renamed = "currentChanged_qw"
|
||||
elsif n == "currentChanged" && s =~ /int/
|
||||
match += ".*int"
|
||||
end
|
||||
elsif c == "QSignalMapper"
|
||||
if n == "mapped" && s =~ /QWidget/
|
||||
renamed = "mapped_qw"
|
||||
match += ".*QWidget"
|
||||
elsif n == "mapped" && s =~ /int/
|
||||
match += ".*int"
|
||||
elsif n == "mapped" && s =~ /QString/
|
||||
renamed = "mapped_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "mapped" && s =~ /QObject/
|
||||
renamed = "mapped_qo"
|
||||
match += ".*QObject"
|
||||
end
|
||||
elsif c == "QComboBox" || c == "QFontComboBox"
|
||||
if n == "activated" && s =~ /QString/
|
||||
renamed = "activated_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "activated" && s =~ /int/
|
||||
match += ".*int"
|
||||
elsif n == "currentIndexChanged" && s =~ /QString/
|
||||
renamed = "currentIndexChanged_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "currentIndexChanged" && s =~ /int/
|
||||
match += ".*int"
|
||||
elsif n == "highlighted" && s =~ /QString/
|
||||
renamed = "highlighted_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "highlighted" && s =~ /int/
|
||||
match += ".*int"
|
||||
end
|
||||
elsif c == "QCompleter"
|
||||
if n == "activated" && s =~ /QString/
|
||||
renamed = "activated_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "activated" && s =~ /QModelIndex/
|
||||
match += ".*QModelIndex"
|
||||
elsif n == "highlighted" && s =~ /QString/
|
||||
renamed = "highlighted_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "highlighted" && s =~ /QModelIndex/
|
||||
match += ".*QModelIndex"
|
||||
end
|
||||
elsif c == "QTextBrowser"
|
||||
if n == "highlighted" && s =~ /QString/
|
||||
renamed = "highlighted_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "highlighted" && s =~ /QUrl/
|
||||
match += ".*QUrl"
|
||||
end
|
||||
elsif c == "QDoubleSpinBox"
|
||||
if n == "valueChanged" && s =~ /QString/
|
||||
renamed = "valueChanged_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "valueChanged" && s =~ /double/
|
||||
match += ".*double"
|
||||
end
|
||||
elsif c == "QSpinBox"
|
||||
if n == "valueChanged" && s =~ /QString/
|
||||
renamed = "valueChanged_qs"
|
||||
match += ".*QString"
|
||||
elsif n == "valueChanged" && s =~ /int/
|
||||
match += ".*int"
|
||||
end
|
||||
elsif c == "QButtonGroup"
|
||||
if n == "buttonClicked" && s =~ /QAbstractButton/
|
||||
renamed = "buttonClicked_qab"
|
||||
match += ".*QAbstractButton"
|
||||
elsif n == "buttonClicked" && s =~ /int/
|
||||
match += ".*int"
|
||||
elsif n == "buttonPressed" && s =~ /QAbstractButton/
|
||||
renamed = "buttonPressed_qab"
|
||||
match += ".*QAbstractButton"
|
||||
elsif n == "buttonPressed" && s =~ /int/
|
||||
match += ".*int"
|
||||
elsif n == "buttonReleased" && s =~ /QAbstractButton/
|
||||
renamed = "buttonReleased_qab"
|
||||
match += ".*QAbstractButton"
|
||||
elsif n == "buttonReleased" && s =~ /int/
|
||||
match += ".*int"
|
||||
end
|
||||
end
|
||||
puts "event(\"#{c}\", /#{match}/, \"#{s}\")"
|
||||
if renamed
|
||||
puts "rename(\"#{c}\", /#{match}/, \"#{renamed}\")"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
Executable
+70
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
# Usage
|
||||
# parse.rb -i prep.cpp -o dump.json
|
||||
#
|
||||
# prep.cpp: preprocessed .cpp file
|
||||
# dump.json: output dump
|
||||
|
||||
$:.push(File.dirname($0))
|
||||
|
||||
require 'oj'
|
||||
require 'treetop'
|
||||
|
||||
Treetop.load "c++"
|
||||
|
||||
input="all.e"
|
||||
output="all.db"
|
||||
|
||||
while ARGV.size > 0
|
||||
o = ARGV.shift
|
||||
if o == "-i"
|
||||
input = ARGV.shift
|
||||
elsif o == "-o"
|
||||
output = ARGV.shift
|
||||
else
|
||||
raise("Invalid option #{o} - usage is 'parse.rb -i prep.cpp -o dump.json'")
|
||||
end
|
||||
end
|
||||
|
||||
input || raise("No input given (use -i)")
|
||||
output || raise("No output given (use -o)")
|
||||
|
||||
text = nil
|
||||
File.open(input, "r") do |file|
|
||||
text = file.read
|
||||
end
|
||||
|
||||
parser = CPPParser.new
|
||||
parser.root = :module
|
||||
p = parser.parse(text)
|
||||
|
||||
if p
|
||||
puts "Input #{input} successfully read."
|
||||
File.open(output, "w") do |file|
|
||||
file.puts(Oj.dump(p.cpp, :mode => :object))
|
||||
end
|
||||
puts "Output file #{output} written."
|
||||
else
|
||||
puts "Failure in line: "+parser.failure_line.to_s
|
||||
puts parser.failure_reason
|
||||
end
|
||||
|
||||
Executable
+3059
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,521 @@
|
||||
|
||||
#
|
||||
# Copyright (C) 2006-2017 Matthias Koefferlein
|
||||
#
|
||||
# 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 CPPObject
|
||||
|
||||
# Propagate setting of the visibility down to the children
|
||||
# (set_visibility will replace the default visibility with public or private)
|
||||
def set_visibility
|
||||
end
|
||||
|
||||
# Inject scoped objects (like "class A::B { ... };") into their target
|
||||
# scope.
|
||||
def inject_scoped
|
||||
end
|
||||
|
||||
# delivers a string representation of the name or nil if the object does not have a name
|
||||
# to contribute
|
||||
def myself
|
||||
nil
|
||||
end
|
||||
|
||||
# delivers a CPPQualifiedId representation of the object's location or nil if the object
|
||||
# does not have a location to contribute
|
||||
def myid
|
||||
nil
|
||||
end
|
||||
|
||||
# sets the CPPQualifiedId
|
||||
def setid(id)
|
||||
end
|
||||
|
||||
# supposed to establish the parent link
|
||||
def set_parent(p)
|
||||
end
|
||||
|
||||
# removes a child from our members
|
||||
def remove(d)
|
||||
end
|
||||
|
||||
# inserts a child into our members
|
||||
def insert(d)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPType
|
||||
|
||||
def func
|
||||
i = self
|
||||
while i.respond_to?(:inner)
|
||||
if i.is_a?(CPPFunc) && (i.inner.is_a?(CPPQualifiedId) || i.inner.is_a?(CPPAnonymousId))
|
||||
return i
|
||||
end
|
||||
i = i.inner
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def return_type
|
||||
rt = self.dup
|
||||
f = self.func
|
||||
if f
|
||||
i = self
|
||||
idup = rt
|
||||
while i.respond_to?(:inner)
|
||||
i = i.inner
|
||||
if i == f
|
||||
idup.inner = CPPAnonymousId::new
|
||||
break
|
||||
end
|
||||
idup.inner = i.dup
|
||||
idup = idup.inner
|
||||
end
|
||||
end
|
||||
rt
|
||||
end
|
||||
|
||||
def name_substituted_type(sub)
|
||||
rt = self.dup
|
||||
i = self
|
||||
idup = rt
|
||||
while i.respond_to?(:inner)
|
||||
ii = i.inner
|
||||
if ii.is_a?(CPPQualifiedId) || ii.is_a?(CPPAnonymousId)
|
||||
idup.inner = sub
|
||||
break
|
||||
end
|
||||
i = ii
|
||||
idup.inner = i.dup
|
||||
idup = idup.inner
|
||||
end
|
||||
rt
|
||||
end
|
||||
|
||||
def anonymous_type
|
||||
name_substituted_type(CPPAnonymousId::new)
|
||||
end
|
||||
|
||||
def renamed_type(name)
|
||||
name_substituted_type(CPPQualifiedId::new(false, [name]))
|
||||
end
|
||||
|
||||
def name
|
||||
i = self
|
||||
while i.respond_to?(:inner)
|
||||
ii = i.inner
|
||||
if ii.is_a?(CPPQualifiedId)
|
||||
return ii.to_s
|
||||
end
|
||||
i = ii
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def is_void?
|
||||
self.concrete.is_a?(CPPPOD) && self.concrete.to_s == "void" && (self.inner.is_a?(CPPAnonymousId) || self.inner.is_a?(CPPQualifiedId))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
module QualifiedNameResolver
|
||||
|
||||
attr_accessor :parent
|
||||
|
||||
def global_scope
|
||||
o = self
|
||||
while o.myself && o.parent
|
||||
o = o.parent
|
||||
end
|
||||
o
|
||||
end
|
||||
|
||||
# requirements
|
||||
# - children -> must deliver a list of child objects
|
||||
# - myself -> must deliver my name
|
||||
|
||||
def set_parent(parent = nil)
|
||||
self.parent = parent
|
||||
@id2obj = {}
|
||||
self.children.each do |d|
|
||||
d.myself && (@id2obj[d.myself] = d)
|
||||
d.set_parent(self)
|
||||
end
|
||||
# Add other children, for example contributed by base classes
|
||||
if self.respond_to?(:other_children)
|
||||
self.other_children.each do |d|
|
||||
d.myself && (@id2obj[d.myself] = d)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def dump_ids
|
||||
@id2obj.keys.sort.each do |k|
|
||||
puts("--> #{k}")
|
||||
end
|
||||
end
|
||||
|
||||
# returns a list of names of child objects
|
||||
def ids
|
||||
(@id2obj || {}).keys.sort
|
||||
end
|
||||
|
||||
def id2obj(id)
|
||||
@id2obj && @id2obj[id]
|
||||
end
|
||||
|
||||
def resolve_qid(qid)
|
||||
|
||||
qid.is_a?(CPPQualifiedId) || raise("Argument of resolve_qid must be a CPPQualifiedId object")
|
||||
|
||||
obj = nil
|
||||
if qid.global && self.parent
|
||||
root = self
|
||||
while root.parent
|
||||
root = root.parent
|
||||
end
|
||||
obj = root.resolve_qid(qid)
|
||||
else
|
||||
obj = id2obj(qid.parts[0].id)
|
||||
if obj && qid.parts.size > 1
|
||||
# The part may be a typedef: resolve it in that case before we proceed
|
||||
while obj && obj.is_a?(CPPTypedef)
|
||||
obj = obj.type.concrete.is_a?(CPPQualifiedId) && self.resolve_qid(obj.type.concrete)
|
||||
end
|
||||
if obj
|
||||
qid_new = qid.dup
|
||||
qid_new.parts = qid.parts[1 .. -1]
|
||||
obj = obj.respond_to?(:resolve_qid) && obj.resolve_qid(qid_new)
|
||||
end
|
||||
end
|
||||
if ! obj && self.parent
|
||||
obj = self.parent.resolve_qid(qid)
|
||||
end
|
||||
end
|
||||
|
||||
obj
|
||||
|
||||
end
|
||||
|
||||
def inject_scoped
|
||||
|
||||
self.children.each do |d|
|
||||
|
||||
d.inject_scoped
|
||||
|
||||
qid = d.myid
|
||||
if qid
|
||||
|
||||
qid.is_a?(CPPQualifiedId) || raise("Argument of resolve_qid must be a CPPQualifiedId object")
|
||||
|
||||
if qid.parts.size > 1
|
||||
|
||||
qid = qid.dup
|
||||
while qid.parts.size > 1
|
||||
obj = id2obj(qid.parts[0].id)
|
||||
if obj
|
||||
qid.parts = qid.parts[1 .. -1]
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if obj && qid.parts.size == 1
|
||||
# This copies the visibility which is not quite correct, since the injection case
|
||||
# is usually used for providing an implementation outside a class. That does not
|
||||
# mean the outside implementation will provide the visibility. Instead a forward
|
||||
# declaration inside the target scope will do. Since that is lost in our implementation
|
||||
# currently that is not possible.
|
||||
self.remove(d)
|
||||
d.setid(qid)
|
||||
obj.insert(d)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPDeclaration
|
||||
|
||||
include QualifiedNameResolver
|
||||
|
||||
def children
|
||||
[]
|
||||
end
|
||||
|
||||
def myself
|
||||
self.type.name
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPEnumDeclaration
|
||||
|
||||
include QualifiedNameResolver
|
||||
|
||||
def children
|
||||
[]
|
||||
end
|
||||
|
||||
def myself
|
||||
self.enum.name.to_s
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPEnumSpec
|
||||
|
||||
include QualifiedNameResolver
|
||||
|
||||
def children
|
||||
[]
|
||||
end
|
||||
|
||||
def myself
|
||||
self.name.to_s
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPStruct
|
||||
|
||||
attr_accessor :parent
|
||||
|
||||
def global_scope
|
||||
self.parent && self.parent.global_scope
|
||||
end
|
||||
|
||||
def set_visibility
|
||||
|
||||
(self.body_decl || []).each do |bd|
|
||||
if bd.respond_to?(:visibility) && bd.visibility == :default
|
||||
if self.kind == :struct || self.kind == :union
|
||||
bd.visibility = :public
|
||||
else
|
||||
bd.visibility = :private
|
||||
end
|
||||
end
|
||||
bd.set_visibility
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPTypedef
|
||||
|
||||
include QualifiedNameResolver
|
||||
|
||||
def myself
|
||||
self.type.name
|
||||
end
|
||||
|
||||
def children
|
||||
[]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPStructDeclaration
|
||||
|
||||
include QualifiedNameResolver
|
||||
|
||||
def children
|
||||
|
||||
# take this chance to set the parent to struct
|
||||
self.struct.parent = self
|
||||
c = self.struct.body_decl || []
|
||||
|
||||
# add enum constants (CPPEnumSpec)
|
||||
(self.struct.body_decl || []).each do |bd|
|
||||
if bd.is_a?(CPPEnumDeclaration) && bd.enum && bd.enum.specs
|
||||
c += bd.enum.specs
|
||||
end
|
||||
end
|
||||
|
||||
c
|
||||
|
||||
end
|
||||
|
||||
def remove(d)
|
||||
self.struct.body_decl.delete(d)
|
||||
end
|
||||
|
||||
def insert(d)
|
||||
self.struct.body_decl << d
|
||||
end
|
||||
|
||||
def other_children
|
||||
|
||||
# add base classes both as sub-namespace and individual parts
|
||||
# and add self so scoping is possible into ourself
|
||||
c = [ self ]
|
||||
|
||||
(self.struct.base_classes || []).each do |bc|
|
||||
bc_obj = self.parent.resolve_qid(bc.class_id)
|
||||
# NOTE: it may look strange to test whether the base class is the class itself but
|
||||
# since we do a half-hearted job of resolving template variants, this may happen
|
||||
# if we derive a template specialization from another one (specifically
|
||||
# "template<class T> struct is_default_constructible : is_default_constructible<> { .. }"
|
||||
if bc_obj != self && bc_obj.is_a?(CPPStructDeclaration)
|
||||
c << bc_obj
|
||||
c += bc_obj.children
|
||||
c += bc_obj.other_children
|
||||
end
|
||||
end
|
||||
|
||||
c
|
||||
|
||||
end
|
||||
|
||||
def myself
|
||||
# forward declarations (struct.body_decl == nil and no base classes) don't produce a name and
|
||||
# will therefore not contribute
|
||||
(self.struct.body_decl || self.struct.base_classes) && self.struct.id.to_s
|
||||
end
|
||||
|
||||
def myid
|
||||
# forward declarations (struct.body_decl == nil and no base classes) don't produce a name and
|
||||
# will therefore not contribute
|
||||
(self.struct.body_decl || self.struct.base_classes) && self.struct.id
|
||||
end
|
||||
|
||||
def setid(id)
|
||||
self.struct.id = id
|
||||
end
|
||||
|
||||
def set_visibility
|
||||
self.struct && self.struct.set_visibility
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPNamespace
|
||||
|
||||
include QualifiedNameResolver
|
||||
|
||||
def children
|
||||
|
||||
# take this opportunity to join identical namespaces
|
||||
if self.members
|
||||
new_members = []
|
||||
ns = {}
|
||||
self.members.each do |d|
|
||||
if d.is_a?(CPPNamespace)
|
||||
if !ns[d.myself]
|
||||
ns[d.myself] = d
|
||||
new_members << d
|
||||
else
|
||||
ns[d.myself].members += d.members
|
||||
end
|
||||
else
|
||||
new_members << d
|
||||
end
|
||||
end
|
||||
self.members = new_members
|
||||
end
|
||||
|
||||
self.members || []
|
||||
|
||||
end
|
||||
|
||||
def other_children
|
||||
# add self so scoping is possible into ourself
|
||||
[ self ]
|
||||
end
|
||||
|
||||
def myself
|
||||
self.name.to_s
|
||||
end
|
||||
|
||||
def remove(d)
|
||||
self.members.delete(d)
|
||||
end
|
||||
|
||||
def insert(d)
|
||||
self.members << d
|
||||
end
|
||||
|
||||
def set_visibility
|
||||
|
||||
(self.members || []).each do |m|
|
||||
if m.respond_to?(:visibility) && m.visibility == :default
|
||||
m.visibility = :public
|
||||
end
|
||||
m.set_visibility
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class CPPModule
|
||||
|
||||
include QualifiedNameResolver
|
||||
|
||||
def children
|
||||
|
||||
# take this opportunity to join identical namespaces
|
||||
new_decls = []
|
||||
ns = {}
|
||||
self.decls.each do |d|
|
||||
if d.is_a?(CPPNamespace)
|
||||
if !ns[d.myself]
|
||||
ns[d.myself] = d
|
||||
new_decls << d
|
||||
else
|
||||
ns[d.myself].members += d.members
|
||||
end
|
||||
else
|
||||
new_decls << d
|
||||
end
|
||||
end
|
||||
|
||||
self.decls = new_decls
|
||||
|
||||
end
|
||||
|
||||
def remove(d)
|
||||
self.decls.delete(d)
|
||||
end
|
||||
|
||||
def insert(d)
|
||||
self.decls << d
|
||||
end
|
||||
|
||||
def myself
|
||||
nil
|
||||
end
|
||||
|
||||
def set_visibility
|
||||
(self.decls || []).each do |d|
|
||||
if d.respond_to?(:visibility) && d.visibility == :default
|
||||
d.visibility = :public
|
||||
end
|
||||
d.set_visibility
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user