From aeba3f5df84c65cad9963d2ee7fa263e0cd69577 Mon Sep 17 00:00:00 2001 From: Matthias Koefferlein Date: Sat, 27 Nov 2021 00:08:50 +0100 Subject: [PATCH] WIP: adjusting simple parser for C++17 (somewhat) --- scripts/mkqtdecl.sh | 19 ++++- scripts/mkqtdecl_common/c++.treetop | 83 +++++++++++++------ scripts/mkqtdecl_common/cpp_classes.rb | 26 ++---- scripts/mkqtdecl_common/cpp_parser_classes.rb | 8 +- scripts/mkqtdecl_common/parse.rb | 2 +- 5 files changed, 85 insertions(+), 53 deletions(-) diff --git a/scripts/mkqtdecl.sh b/scripts/mkqtdecl.sh index 8a0f462e6..a1459105b 100755 --- a/scripts/mkqtdecl.sh +++ b/scripts/mkqtdecl.sh @@ -7,13 +7,14 @@ # framework is based on a C++ parser and a configuration file that specifies details # about the translation. # -# By default, the script will take the Qt headers from /opt/qt/4.6.3 and /opt/qt/5.5.1 -# for Qt4 and Qt5 respectively. +# By default, the script will take the Qt headers from /opt/qt/4.6.3, /opt/qt/5.5.1 +# and /opt/qt/6.2.1 for Qt4, Qt5 and Qt6 respectively. # # Call it from project level as # # ./scripts/mkqtdecl.sh -update # Qt4 # ./scripts/mkqtdecl.sh -update -qt5 # Qt5 +# ./scripts/mkqtdecl.sh -update -qt6 # Qt6 # # For more options see # @@ -43,14 +44,18 @@ diff=0 reuse=0 qt="/opt/qt/4.6.3/include" qt5="/opt/qt/5.5.1/include" +qt6="/opt/qt/6.2.1/include" inst_dir_common=`pwd`/scripts/mkqtdecl_common inst_dir4=`pwd`/scripts/mkqtdecl4 inst_dir5=`pwd`/scripts/mkqtdecl5 +inst_dir6=`pwd`/scripts/mkqtdecl6 src_dir=`pwd`/src src_name4=gsiqt/qt4 src_name5=gsiqt/qt5 +src_name6=gsiqt/qt6 qt_mods4="QtCore QtGui QtDesigner QtNetwork QtSql QtXml QtUiTools" qt_mods5="QtCore QtGui QtWidgets QtDesigner QtNetwork QtPrintSupport QtSql QtSvg QtXml QtXmlPatterns QtMultimedia QtUiTools" +qt_mods6="QtCore QtGui QtWidgets QtDesigner QtNetwork QtPrintSupport QtSql QtSvg QtXml QtMultimedia QtUiTools QtCore5Compat" src_name=$src_name4 inst_dir=$inst_dir4 @@ -73,6 +78,7 @@ while [ "$1" != "" ]; do echo " mkqtdecl.sh -diff Show differences - don't produce and don't synchronize" echo " mkqtdecl.sh -qt path_to_include Use the specified include path" echo " mkqtdecl.sh -qt5 Use setup for Qt 5.x (use before -qt)" + echo " mkqtdecl.sh -qt6 Use setup for Qt 6.x (use before -qt)" echo " mkqtdecl.sh -reuse Don't parse C++ container again" exit 0 ;; @@ -102,6 +108,13 @@ while [ "$1" != "" ]; do qt_mods="$qt_mods5" src_name="$src_name5" ;; + -qt6) + qt="$qt6" + work_dir="mkqtdecl6.tmp" + inst_dir="$inst_dir6" + qt_mods="$qt_mods6" + src_name="$src_name6" + ;; *) echo "*** ERROR: unknown command option $a" exit 1 @@ -181,7 +194,7 @@ if [ $update != 0 ]; then echo "Running gcc preprocessor .." # By using -D_GCC_LIMITS_H_ we make the gcc not include constants such as ULONG_MAX which will # remain as such. This way the generated code is more generic. - gcc -std=gnu++98 -I$qt -fPIC -D_GCC_LIMITS_H_ -E -o allofqt.x allofqt.cpp + gcc -std=c++17 -I$qt -fPIC -D_GCC_LIMITS_H_ -E -o allofqt.x allofqt.cpp echo "Stripping hash lines .." egrep -v '^#' allofqt.e diff --git a/scripts/mkqtdecl_common/c++.treetop b/scripts/mkqtdecl_common/c++.treetop index 44272c002..f20cfd293 100644 --- a/scripts/mkqtdecl_common/c++.treetop +++ b/scripts/mkqtdecl_common/c++.treetop @@ -50,7 +50,29 @@ grammar CPP end rule a - s ( "__attribute__" s attribute_value s / "__asm" s attribute_value s / "__extension__" s / "decltype" s attribute_value s )* + s ( "__attribute__" s attribute_value s / + "__asm" s attribute_value s / + "constexpr" ![a-zA-Z0-9_] s / + "__extension__" s / + "__inline" s / + "__m64" s / + "__m128" s / + "__m128d" s / + "__m128i" s / + "__m256" s / + "__m256d" s / + "__m256i" s / + "__m512" s / + "__m512d" s / + "__m512i" s / + "__mmask8" s / + "__mmask16" s / + "__v8df" s / + "__v8di" s / + "__v16sf" s / + "__v16si" s / + "decltype" s attribute_value s / + "[[" s block s "]]" s )* end rule unary_op @@ -147,13 +169,15 @@ grammar CPP rule member_declaration_wo_semicolon template:( d:template_decl s )? - attr:( ( explicit_key / mutable_key / storage_class / inline_spec / virtual_spec / constexpr_key ) s )* + a + attr:( ( explicit_key / mutable_key / 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 )? + ( trailing_return_type )? a ( "{" s block s "}" / @@ -163,13 +187,15 @@ grammar CPP rule member_declaration_w_semicolon template:( d:template_decl s )? - attr:( ( explicit_key / mutable_key / storage_class / inline_spec / virtual_spec / constexpr_key ) s )* + a + attr:( ( explicit_key / mutable_key / 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 )? + ( trailing_return_type )? a ( "{" s block s "}" / @@ -202,7 +228,7 @@ grammar CPP # 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 "*" ) ) + qualified_id s ( "..." s )? !( "(" !( s "*" ) ) end rule typeof @@ -222,11 +248,11 @@ grammar CPP end rule concrete_type - ( constexpr_key / class_or_struct_type / enum_type / float_type / char_type / int_type / bool_type / void_type / typeof / class_id )? + ( class_or_struct_type / enum_type / float_type / char_type / int_type / bool_type / void_type / typeof / class_id )? end rule cv - ( constexpr_key / "const" ![a-zA-Z0-9_] / "__const" ![a-zA-Z0-9_] / "volatile" ![a-zA-Z0-9_] / "__volatile" ![a-zA-Z0-9_] ) + ( "const" ![a-zA-Z0-9_] / "__const" ![a-zA-Z0-9_] / "volatile" ![a-zA-Z0-9_] / "__volatile" ![a-zA-Z0-9_] ) end rule pointer @@ -256,11 +282,15 @@ grammar CPP end rule noexcept_spec - "noexcept" ( s "=" s block / s "(" s block ")" )? + "noexcept" ( s "(" s block s ")" )? + end + + rule func_assign_spec + "=" s ( "delete" / "0" )? end rule func_spec - "(" s fa:( a:func_args )? s ")" cvspec:( s cv:cv )? ( s "throw" s "(" s ( type_wo_comma s )? ")" / s noexcept_spec )* ( s override_key )? a + "(" s fa:( a:func_args )? s ")" cvspec:( s cv:cv )? ( s "throw" s "(" s ( type_wo_comma s )? ")" / s noexcept_spec / s func_assign_spec / s override_key )* a end rule member_pointer @@ -278,7 +308,7 @@ grammar CPP pointer / reference / member_pointer / - ( "__restrict" ![a-zA-Z0-9_] s )? qualified_id + ( "__restrict" ![a-zA-Z0-9_] s / "..." s )* qualified_id ) pfx:( s spec:( array_spec / func_spec ) )* @@ -310,7 +340,7 @@ grammar CPP rule type_for_template cvspec:( cv:cv s )? a - ( "typename" ![a-zA-Z0-9_] s )? + ( ( "typename" / "class" ) ![a-zA-Z0-9_] s ( "..." s )? )? ct:concrete_type il:( s t:inner_type )? @@ -324,19 +354,15 @@ grammar CPP "override" ![a-zA-Z0-9_] end - rule constexpr_key - "constexpr" ![a-zA-Z0-9_] - end - rule inline_spec "inline" ![a-zA-Z0-9_] 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 ">" / + "(" 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 / "?" / "::" / "." / ":" / ";" + id ( s "{" s block s "}" )? / unary_op / bin_op_wo_gt / "?" / "::" / "." / ":" / ";" end rule block_wo_gt @@ -347,7 +373,7 @@ grammar CPP 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 / "?" / "::" / "." / ":" + id ( s "{" s block s "}" )? / unary_op / bin_op / "?" / "::" / "." / ":" end rule block @@ -375,25 +401,29 @@ grammar CPP end rule template_decl_arg - ( "class" / "typename" ) ![a-zA-Z0-9_] s id:id dtspec:( s "=" s dt:type_for_template )? / - t:type_for_template initspec:( s "=" s init:block_wo_gt )? + t:type_for_template dtspec:( s "=" s dt:block_wo_gt )? end rule template_decl "template" s "<" s ( !">" template_decl_arg s ( "," s template_decl_arg )* )? s ">" end + rule trailing_return_type + "->" s ( "decltype" s "(" s block s ")" / type ) + end + rule declaration_w_semicolon template:( d:template_decl s )? template_member:( d_member:template_decl s )? - attr:( ( storage_class / inline_spec / constexpr_key ) s )* a - ( constexpr_key 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 )? + ( trailing_return_type )? a ( "{" s block s "}" / @@ -403,14 +433,15 @@ grammar CPP rule declaration_wo_semicolon template:( d:template_decl s )? - attr:( ( storage_class / inline_spec / constexpr_key ) s )* a - ( constexpr_key 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 )? + ( trailing_return_type )? a ( "{" s block s "}" / @@ -432,8 +463,12 @@ grammar CPP a "{" decls:( a ( ";" / typedef / namespace / extern_decl / declaration ) )* s "}" end + rule asm + "asm" s "(" s block s ")" + end + rule module - ( a ( ";" / static_assert / using / typedef / namespace / extern_decl / declaration ) )* s + ( a ( ";" / static_assert / using / typedef / namespace / extern_decl / declaration / asm ) )* s end end diff --git a/scripts/mkqtdecl_common/cpp_classes.rb b/scripts/mkqtdecl_common/cpp_classes.rb index c4ff1a925..7168e38eb 100644 --- a/scripts/mkqtdecl_common/cpp_classes.rb +++ b/scripts/mkqtdecl_common/cpp_classes.rb @@ -469,29 +469,19 @@ class CPPFriendDecl < CPPObject end # @brief A type template argument (with an optional initializer) -# @attribute id The name of the argument (a string) +# @attribute type The template argument (a type) # @attribute def_type The default type (nil or a CPPType object) class CPPClassTemplateArg < CPPObject - attr_accessor :id, :def_type - def_initializer :id, :def_type + attr_accessor :type, :def_type + def_initializer :type, :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) : "") + if self.def_type + self.type.to_s + "=" + self.def_type.to_s + else + self.type.to_s + end end end diff --git a/scripts/mkqtdecl_common/cpp_parser_classes.rb b/scripts/mkqtdecl_common/cpp_parser_classes.rb index 187c0d8e1..beeba344d 100644 --- a/scripts/mkqtdecl_common/cpp_parser_classes.rb +++ b/scripts/mkqtdecl_common/cpp_parser_classes.rb @@ -404,13 +404,7 @@ 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) + CPPClassTemplateArg::new(t.cpp, dtspec.nonterminal? ? dtspec.cpp : nil) end end diff --git a/scripts/mkqtdecl_common/parse.rb b/scripts/mkqtdecl_common/parse.rb index d91f46847..1298ab1e1 100755 --- a/scripts/mkqtdecl_common/parse.rb +++ b/scripts/mkqtdecl_common/parse.rb @@ -29,7 +29,7 @@ $:.push(File.dirname($0)) require 'oj' require 'treetop' -Treetop.load "c++" +Treetop.load File.join(File.dirname($0), "c++") input="all.e" output="all.db"