From b8d7516e93eff1143f7e59a6fd133699c2f5c71f Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 13:12:21 +0100 Subject: [PATCH] Successful use of ClassGrammar in Module.cpp --- wrap/Class.h | 85 ++++++++++++------------ wrap/Module.cpp | 140 +++++---------------------------------- wrap/tests/testClass.cpp | 3 +- 3 files changed, 60 insertions(+), 168 deletions(-) diff --git a/wrap/Class.h b/wrap/Class.h index bc538fc7d..8072c50f6 100644 --- a/wrap/Class.h +++ b/wrap/Class.h @@ -162,11 +162,12 @@ private: // http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html struct ClassGrammar: public classic::grammar { - Class& result_; ///< successful parse will be placed in here + Class& cls_; ///< successful parse will be placed in here + Template& template_; ///< result needs to be visible outside /// Construct type grammar and specify where result is placed - ClassGrammar(Class& result) : - result_(result) { + ClassGrammar(Class& cls, Template& t) : + cls_(cls), template_(t) { } /// Definition of type grammar @@ -186,8 +187,7 @@ struct ClassGrammar: public classic::grammar { ReturnValue retVal0, retVal; ReturnValueGrammar returnValue_g; - // template - Template methodTemplate, classTemplate; + Template methodTemplate; TemplateGrammar methodTemplate_g, classTemplate_g; std::string methodName; @@ -195,35 +195,27 @@ struct ClassGrammar: public classic::grammar { // Parent class Qualified possibleParent; - TypeGrammar classParent_p; + TypeGrammar classParent_g; - classic::rule templateList_p, constructor_p, methodName_p, - method_p, staticMethodName_p, static_method_p, functions_p, class_p; + classic::rule constructor_p, methodName_p, method_p, + staticMethodName_p, static_method_p, templateList_p, classParent_p, + functions_p, class_p; definition(ClassGrammar const& self) : argumentList_g(args), returnValue_g(retVal), // - methodTemplate_g(methodTemplate), classTemplate_g(classTemplate), // - T(true), F(false), classParent_p(possibleParent) { + methodTemplate_g(methodTemplate), classTemplate_g(self.template_), // + T(true), F(false), classParent_g(possibleParent) { using namespace classic; bool verbose = false; // TODO - // template - templateList_p = (str_p("template") >> '<' - >> name_p[push_back_a(self.result_.templateArgs)] - >> *(',' >> name_p[push_back_a(self.result_.templateArgs)]) >> '>'); - - // parse class constructor - constructor_p = - (className_p >> argumentList_g >> ';' >> !comments_p)[bl::bind( - &Constructor::push_back, bl::var(constructor), bl::var(args))][clear_a( - args)]; - - // TODO why is this not used anywhere? -// vector namespaces_return; /// namespace for current return type -// Rule namespace_ret_p = namespace_p[push_back_a(namespaces_return)] -// >> str_p("::"); + // ConstructorGrammar + constructor_p = (className_p >> argumentList_g >> ';' >> !comments_p) // + [bl::bind(&Constructor::push_back, bl::var(constructor), + bl::var(args))] // + [clear_a(args)]; + // MethodGrammar methodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; // gtsam::Values retract(const gtsam::VectorValues& delta) const; @@ -231,40 +223,47 @@ struct ClassGrammar: public classic::grammar { >> (returnValue_g >> methodName_p[assign_a(methodName)] >> argumentList_g >> !str_p("const")[assign_a(isConst, T)] >> ';' >> *comments_p) // - [bl::bind(&Class::addMethod, bl::var(self.result_), verbose, + [bl::bind(&Class::addMethod, bl::var(self.cls_), verbose, bl::var(isConst), bl::var(methodName), bl::var(args), bl::var(retVal), bl::var(methodTemplate))] // - [assign_a(retVal, retVal0)] // - [clear_a(args)][clear_a(methodTemplate)] // - [assign_a(isConst, F)]; + [assign_a(retVal, retVal0)][clear_a(args)] // + [clear_a(methodTemplate)][assign_a(isConst, F)]; + // StaticMethodGrammar staticMethodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; static_method_p = (str_p("static") >> returnValue_g >> staticMethodName_p[assign_a(methodName)] >> argumentList_g >> ';' >> *comments_p) // [bl::bind(&StaticMethod::addOverload, - bl::var(self.result_.static_methods)[bl::var(methodName)], + bl::var(self.cls_.static_methods)[bl::var(methodName)], bl::var(methodName), bl::var(args), bl::var(retVal), boost::none, verbose)] // [assign_a(retVal, retVal0)][clear_a(args)]; + // template + templateList_p = (str_p("template") >> '<' + >> name_p[push_back_a(self.cls_.templateArgs)] + >> *(',' >> name_p[push_back_a(self.cls_.templateArgs)]) >> '>'); + + // parse a full class + classParent_p = (':' >> classParent_g >> '{') // + [bl::bind(&Class::assignParent, bl::var(self.cls_), + bl::var(possibleParent))][clear_a(possibleParent)]; + functions_p = constructor_p | method_p | static_method_p; // parse a full class - class_p = (!(classTemplate_g[push_back_a(self.result_.templateArgs, - classTemplate.argName())] | templateList_p) - >> !(str_p("virtual")[assign_a(self.result_.isVirtual, true)]) - >> str_p("class") >> className_p[assign_a(self.result_.name_)] - >> ((':' >> classParent_p >> '{')[bl::bind(&Class::assignParent, - bl::var(self.result_), bl::var(possibleParent))][clear_a( - possibleParent)] | '{') >> *(functions_p | comments_p) - >> str_p("};")) // + class_p = (!(classTemplate_g[push_back_a(self.cls_.templateArgs, + self.template_.argName())] | templateList_p) + >> !(str_p("virtual")[assign_a(self.cls_.isVirtual, true)]) + >> str_p("class") >> className_p[assign_a(self.cls_.name_)] + >> (classParent_p | '{') >> // + *(functions_p | comments_p) >> str_p("};")) // [bl::bind(&Constructor::initializeOrCheck, bl::var(constructor), - bl::var(self.result_.name_), boost::none, verbose)][assign_a( - self.result_.constructor, constructor)] // - [assign_a(self.result_.deconstructor.name, self.result_.name_)] // - [clear_a(classTemplate)] // + bl::var(self.cls_.name_), boost::none, verbose)][assign_a( + self.cls_.constructor, constructor)] // + [assign_a(self.cls_.deconstructor.name, self.cls_.name_)] // [assign_a(constructor, constructor0)]; } @@ -276,5 +275,5 @@ struct ClassGrammar: public classic::grammar { }; // ClassGrammar -} // \namespace wrap +}// \namespace wrap diff --git a/wrap/Module.cpp b/wrap/Module.cpp index 917130f5c..907ad1472 100644 --- a/wrap/Module.cpp +++ b/wrap/Module.cpp @@ -22,19 +22,6 @@ #include "TypeAttributesTable.h" #include "utilities.h" -//#define BOOST_SPIRIT_DEBUG -#include "spirit.h" - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" -#endif -#include -#include -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#include #include #include #include @@ -111,15 +98,24 @@ void Module::parseMarkup(const std::string& data) { typedef rule Rule; BasicRules basic; - // TODO, do we really need cls here? Non-local + vector namespaces; // current namespace tag + + // parse a full class Class cls0(verbose),cls(verbose); - + Template classTemplate; + ClassGrammar class_g(cls,classTemplate); + Rule class_p = class_g // + [assign_a(cls.namespaces_, namespaces)] + [bl::bind(&handle_possible_template, bl::var(classes), bl::var(cls), + bl::var(classTemplate.argValues()))] + [clear_a(classTemplate)] // + [assign_a(cls,cls0)]; + // parse "gtsam::Pose2" and add to singleInstantiation.typeList TemplateInstantiationTypedef singleInstantiation, singleInstantiation0; TypeListGrammar<'<','>'> typelist_g(singleInstantiation.typeList); // typedef gtsam::RangeFactor RangeFactorPosePoint2; - vector namespaces; // current namespace tag TypeGrammar instantiationClass_g(singleInstantiation.class_); Rule templateSingleInstantiation_p = (str_p("typedef") >> instantiationClass_g >> @@ -130,101 +126,22 @@ void Module::parseMarkup(const std::string& data) { [push_back_a(templateInstantiationTypedefs, singleInstantiation)] [assign_a(singleInstantiation, singleInstantiation0)]; - // template - Rule templateList_p = - (str_p("template") >> - '<' >> basic.name_p[push_back_a(cls.templateArgs)] >> *(',' >> basic.name_p[push_back_a(cls.templateArgs)]) >> - '>'); - // NOTE: allows for pointers to all types ArgumentList args; ArgumentListGrammar argumentList_g(args); - // parse class constructor - Constructor constructor0(verbose), constructor(verbose); - Rule constructor_p = - (basic.className_p >> argumentList_g >> ';' >> !basic.comments_p) - [bl::bind(&Constructor::push_back, bl::var(constructor), bl::var(args))] - [clear_a(args)]; - vector namespaces_return; /// namespace for current return type Rule namespace_ret_p = basic.namespace_p[push_back_a(namespaces_return)] >> str_p("::"); ReturnValue retVal0, retVal; ReturnValueGrammar returnValue_g(retVal); - Rule methodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; - - // template - Template methodTemplate; - TemplateGrammar methodTemplate_g(methodTemplate); + Rule globalFunctionName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; - // gtsam::Values retract(const gtsam::VectorValues& delta) const; - string methodName; - bool isConst, isConst0 = false; - Rule method_p = - !methodTemplate_g >> - (returnValue_g >> methodName_p[assign_a(methodName)] >> - argumentList_g >> - !str_p("const")[assign_a(isConst,true)] >> ';' >> *basic.comments_p) - [bl::bind(&Class::addMethod, bl::var(cls), verbose, bl::var(isConst), - bl::var(methodName), bl::var(args), bl::var(retVal), - bl::var(methodTemplate))] - [assign_a(retVal,retVal0)] - [clear_a(args)] - [clear_a(methodTemplate)] - [assign_a(isConst,isConst0)]; - - Rule staticMethodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; - - Rule static_method_p = - (str_p("static") >> returnValue_g >> staticMethodName_p[assign_a(methodName)] >> - argumentList_g >> ';' >> *basic.comments_p) - [bl::bind(&StaticMethod::addOverload, - bl::var(cls.static_methods)[bl::var(methodName)], - bl::var(methodName), bl::var(args), bl::var(retVal), boost::none,verbose)] - [assign_a(retVal,retVal0)] - [clear_a(args)]; - - Rule functions_p = constructor_p | method_p | static_method_p; - - // template - Template classTemplate; - TemplateGrammar classTemplate_g(classTemplate); - - // Parent class - Qualified possibleParent; - TypeGrammar classParent_p(possibleParent); - - // parse a full class - Rule class_p = - eps_p[assign_a(cls,cls0)] - >> (!(classTemplate_g - [push_back_a(cls.templateArgs, classTemplate.argName())] - | templateList_p) - >> !(str_p("virtual")[assign_a(cls.isVirtual, true)]) - >> str_p("class") - >> basic.className_p[assign_a(cls.name_)] - >> ((':' >> classParent_p >> '{') - [bl::bind(&Class::assignParent, bl::var(cls), bl::var(possibleParent))] - [clear_a(possibleParent)] | '{') - >> *(functions_p | basic.comments_p) - >> str_p("};")) - [bl::bind(&Constructor::initializeOrCheck, bl::var(constructor), - bl::var(cls.name_), boost::none, verbose)] - [assign_a(cls.constructor, constructor)] - [assign_a(cls.namespaces_, namespaces)] - [assign_a(cls.deconstructor.name,cls.name_)] - [bl::bind(&handle_possible_template, bl::var(classes), bl::var(cls), - bl::var(classTemplate.argValues()))] - [clear_a(classTemplate)] - [assign_a(constructor, constructor0)] - [assign_a(cls,cls0)]; - // parse a global function Qualified globalFunction; Rule global_function_p = - (returnValue_g >> staticMethodName_p[assign_a(globalFunction.name_)] >> + (returnValue_g >> globalFunctionName_p[assign_a(globalFunction.name_)] >> argumentList_g >> ';' >> *basic.comments_p) [assign_a(globalFunction.namespaces_,namespaces)] [bl::bind(&GlobalFunction::addOverload, @@ -269,37 +186,12 @@ void Module::parseMarkup(const std::string& data) { Rule module_p = *module_content_p >> !end_p; - //---------------------------------------------------------------------------- - // for debugging, define BOOST_SPIRIT_DEBUG -# ifdef BOOST_SPIRIT_DEBUG - BOOST_SPIRIT_DEBUG_NODE(className_p); - BOOST_SPIRIT_DEBUG_NODE(classPtr_p); - BOOST_SPIRIT_DEBUG_NODE(classRef_p); - BOOST_SPIRIT_DEBUG_NODE(basisType_p); - BOOST_SPIRIT_DEBUG_NODE(name_p); - BOOST_SPIRIT_DEBUG_NODE(argument_p); - BOOST_SPIRIT_DEBUG_NODE(argumentList_g); - BOOST_SPIRIT_DEBUG_NODE(constructor_p); - BOOST_SPIRIT_DEBUG_NODE(returnType1_p); - BOOST_SPIRIT_DEBUG_NODE(returnType2_p); - BOOST_SPIRIT_DEBUG_NODE(pair_p); - BOOST_SPIRIT_DEBUG_NODE(void_p); - BOOST_SPIRIT_DEBUG_NODE(returnValue_g); - BOOST_SPIRIT_DEBUG_NODE(methodName_p); - BOOST_SPIRIT_DEBUG_NODE(method_p); - BOOST_SPIRIT_DEBUG_NODE(class_p); - BOOST_SPIRIT_DEBUG_NODE(namespace_def_p); - BOOST_SPIRIT_DEBUG_NODE(module_p); -# endif - //---------------------------------------------------------------------------- - // and parse contents parse_info info = parse(data.c_str(), module_p, space_p); if(!info.full) { printf("parsing stopped at \n%.20s\n",info.stop); - cout << "Stopped near:\n" - "class '" << cls.name_ << "'\n" - "method '" << methodName << "'" << endl; + cout << "Stopped in:\n" + "class '" << cls.name_ << "'" << endl; throw ParseFailed((int)info.length); } diff --git a/wrap/tests/testClass.cpp b/wrap/tests/testClass.cpp index 1b7cfe31a..756b6668d 100644 --- a/wrap/tests/testClass.cpp +++ b/wrap/tests/testClass.cpp @@ -89,7 +89,8 @@ TEST( Class, Grammar ) { // Create type grammar that will place result in cls Class cls; - ClassGrammar g(cls); + Template t; + ClassGrammar g(cls, t); EXPECT(parse("class Point2 {\n};", g, space_p).full);