From f00f62d89fdcd5ca2d49fbdd4efe41ab4fc3fd64 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 11:24:53 +0100 Subject: [PATCH 01/13] Much better way of handling local variables in grammar --- wrap/Argument.h | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/wrap/Argument.h b/wrap/Argument.h index 3b7a13ee3..fd7e82061 100644 --- a/wrap/Argument.h +++ b/wrap/Argument.h @@ -171,27 +171,28 @@ struct ArgumentListGrammar: public classic::grammar { wrap::ArgumentList& result_; ///< successful parse will be placed in here - const Argument arg0; ///< used to reset arg - mutable Argument arg; ///< temporary argument for use during parsing - ArgumentGrammar argument_g; ///< single Argument parser - /// Construct type grammar and specify where result is placed ArgumentListGrammar(wrap::ArgumentList& result) : - result_(result), argument_g(arg) { + result_(result) { } /// Definition of type grammar template struct definition { + const Argument arg0; ///< used to reset arg + Argument arg; ///< temporary argument for use during parsing + ArgumentGrammar argument_g; ///< single Argument parser + classic::rule argument_p, argumentList_p; - definition(ArgumentListGrammar const& self) { + definition(ArgumentListGrammar const& self) : + argument_g(arg) { using namespace classic; - argument_p = self.argument_g // - [classic::push_back_a(self.result_, self.arg)] // - [assign_a(self.arg, self.arg0)]; + argument_p = argument_g // + [classic::push_back_a(self.result_, arg)] // + [assign_a(arg, arg0)]; argumentList_p = '(' >> !argument_p >> *(',' >> argument_p) >> ')'; } From 6bdba5c17f2052e8a04eba801563057b6378addb Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 11:27:41 +0100 Subject: [PATCH 02/13] Same change for TypeList --- wrap/Qualified.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/wrap/Qualified.h b/wrap/Qualified.h index 000d749ec..6a1db1055 100644 --- a/wrap/Qualified.h +++ b/wrap/Qualified.h @@ -222,25 +222,26 @@ struct TypeListGrammar: public classic::grammar > { typedef std::vector TypeList; TypeList& result_; ///< successful parse will be placed in here - mutable wrap::Qualified type; // temporary type for use during parsing - TypeGrammar type_g; - /// Construct type grammar and specify where result is placed TypeListGrammar(TypeList& result) : - result_(result), type_g(type) { + result_(result) { } /// Definition of type grammar template struct definition { + mutable wrap::Qualified type; ///< temporary for use during parsing + TypeGrammar type_g; ///< Individual Type grammars + classic::rule type_p, typeList_p; - definition(TypeListGrammar const& self) { + definition(TypeListGrammar const& self) : + type_g(type) { using namespace classic; - type_p = self.type_g // - [push_back_a(self.result_, self.type)] // - [clear_a(self.type)]; + + type_p = type_g[push_back_a(self.result_, type)][clear_a(type)]; + typeList_p = OPEN >> !type_p >> *(',' >> type_p) >> CLOSE; } From 6981a1229d52620a060d904516b81052b0b91244 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 11:40:50 +0100 Subject: [PATCH 03/13] Removed mutable --- wrap/Qualified.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/Qualified.h b/wrap/Qualified.h index 6a1db1055..bcc4c0829 100644 --- a/wrap/Qualified.h +++ b/wrap/Qualified.h @@ -231,7 +231,7 @@ struct TypeListGrammar: public classic::grammar > { template struct definition { - mutable wrap::Qualified type; ///< temporary for use during parsing + wrap::Qualified type; ///< temporary for use during parsing TypeGrammar type_g; ///< Individual Type grammars classic::rule type_p, typeList_p; From 12791737e0c07cd5066ea0e8be0e9acdcea996d1 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 11:41:09 +0100 Subject: [PATCH 04/13] First non-passing grammar test --- wrap/tests/testClass.cpp | 108 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 1 deletion(-) diff --git a/wrap/tests/testClass.cpp b/wrap/tests/testClass.cpp index 0ceff500b..ffd5deb6a 100644 --- a/wrap/tests/testClass.cpp +++ b/wrap/tests/testClass.cpp @@ -46,7 +46,7 @@ TEST( Class, OverloadingMethod ) { EXPECT_LONGS_EQUAL(1, cls.method(name).nrOverloads()); // add an overload w different argument list - args.push_back(Argument(Qualified("Vector",Qualified::EIGEN),"v")); + args.push_back(Argument(Qualified("Vector", Qualified::EIGEN), "v")); cls.addMethod(verbose, is_const, name, args, retVal, tmplate); EXPECT_LONGS_EQUAL(1, cls.nrMethods()); EXPECT_LONGS_EQUAL(2, cls.method(name).nrOverloads()); @@ -82,6 +82,112 @@ TEST( Class, TemplatedMethods ) { EXPECT(cls.exists(name+"Point3")); } +/* ************************************************************************* */ +// 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 + + /// Construct type grammar and specify where result is placed + ClassGrammar(Class& result) : + result_(result) { + } + + /// Definition of type grammar + template + struct definition { + + classic::rule class_p; + + definition(ClassGrammar const& self) { + using namespace classic; + + class_p = str_p("class"); + } + + classic::rule const& start() const { + return class_p; + } + + }; +}; +// ClassGrammar + +/* ************************************************************************* */ +TEST( wrap, Small ) { + + using classic::space_p; + + // Create type grammar that will place result in cls + Class cls; + ClassGrammar g(cls); + + string markup( + string("class Point2 { \n") + + string(" double x() const; \n") + // Method 1 + string(" Matrix returnMatrix() const; \n") + // Method 2 + string(" Point2 returnPoint2() const; \n") + // Method 3 + string(" static Vector returnVector(); \n") + // Static Method 1 + string("};\n")); + + EXPECT(parse(markup.c_str(), g, space_p).full); + + // check return types + EXPECT(assert_equal("Point2", cls.name())); + EXPECT(!cls.isVirtual); + EXPECT(cls.namespaces().empty()); + LONGS_EQUAL(3, cls.nrMethods()); + LONGS_EQUAL(1, cls.static_methods.size()); + + // Method 1 + Method m1 = cls.method("x"); + EXPECT(assert_equal("x", m1.name())); + EXPECT(m1.isConst()); + LONGS_EQUAL(1, m1.nrOverloads()); + + ReturnValue rv1 = m1.returnValue(0); + EXPECT(!rv1.isPair); + EXPECT(!rv1.type1.isPtr); + EXPECT(assert_equal("double", rv1.type1.name())); + EXPECT_LONGS_EQUAL(ReturnType::BASIS, rv1.type1.category); + + // Method 2 + Method m2 = cls.method("returnMatrix"); + EXPECT(assert_equal("returnMatrix", m2.name())); + EXPECT(m2.isConst()); + LONGS_EQUAL(1, m2.nrOverloads()); + + ReturnValue rv2 = m2.returnValue(0); + EXPECT(!rv2.isPair); + EXPECT(!rv2.type1.isPtr); + EXPECT(assert_equal("Matrix", rv2.type1.name())); + EXPECT_LONGS_EQUAL(ReturnType::EIGEN, rv2.type1.category); + + // Method 3 + Method m3 = cls.method("returnPoint2"); + EXPECT(assert_equal("returnPoint2", m3.name())); + EXPECT(m3.isConst()); + LONGS_EQUAL(1, m3.nrOverloads()); + + ReturnValue rv3 = m3.returnValue(0); + EXPECT(!rv3.isPair); + EXPECT(!rv3.type1.isPtr); + EXPECT(assert_equal("Point2", rv3.type1.name())); + EXPECT_LONGS_EQUAL(ReturnType::CLASS, rv3.type1.category); + + // Static Method 1 + // static Vector returnVector(); + StaticMethod sm1 = cls.static_methods.at("returnVector"); + EXPECT(assert_equal("returnVector", sm1.name())); + LONGS_EQUAL(1, sm1.nrOverloads()); + + ReturnValue rv4 = sm1.returnValue(0); + EXPECT(!rv4.isPair); + EXPECT(!rv4.type1.isPtr); + EXPECT(assert_equal("Vector", rv4.type1.name())); + EXPECT_LONGS_EQUAL(ReturnType::EIGEN, rv4.type1.category); +} + /* ************************************************************************* */ int main() { TestResult tr; From f035b12f4688ecd7aa0c732a8fcb78757e55e046 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 12:34:54 +0100 Subject: [PATCH 05/13] Successful parse! --- wrap/tests/testClass.cpp | 144 +++++++++++++++++++++++++++++++++++---- 1 file changed, 132 insertions(+), 12 deletions(-) diff --git a/wrap/tests/testClass.cpp b/wrap/tests/testClass.cpp index ffd5deb6a..f3d2c14d1 100644 --- a/wrap/tests/testClass.cpp +++ b/wrap/tests/testClass.cpp @@ -83,6 +83,37 @@ TEST( Class, TemplatedMethods ) { } /* ************************************************************************* */ +#include "../Module.h" +#include "../FileWriter.h" +#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 + +#include +#include + +using namespace std; +using namespace wrap; +using namespace BOOST_SPIRIT_CLASSIC_NS; +namespace bl = boost::lambda; +namespace fs = boost::filesystem; + // http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html struct ClassGrammar: public classic::grammar { @@ -95,14 +126,101 @@ struct ClassGrammar: public classic::grammar { /// Definition of type grammar template - struct definition { + struct definition: BasicRules { - classic::rule class_p; + using BasicRules::name_p; + using BasicRules::className_p; + using BasicRules::comments_p; + + // NOTE: allows for pointers to all types + ArgumentList args; + ArgumentListGrammar argumentList_g; + + Constructor constructor0, constructor; + + ReturnValue retVal0, retVal; + ReturnValueGrammar returnValue_g; + + // template + Template methodTemplate, classTemplate; + TemplateGrammar methodTemplate_g, classTemplate_g; + + string methodName; + bool isConst, T, F; + + // Parent class + Qualified possibleParent; + TypeGrammar classParent_p; + + classic::rule templateList_p, constructor_p, methodName_p, + method_p, staticMethodName_p, static_method_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) { - definition(ClassGrammar const& self) { using namespace classic; + bool verbose = false; // TODO - class_p = str_p("class"); + // 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("::"); + + methodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; + + // gtsam::Values retract(const gtsam::VectorValues& delta) const; + method_p = !methodTemplate_g + >> (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::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)]; + + 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(methodName), bl::var(args), bl::var(retVal), boost::none, + verbose)] // + [assign_a(retVal, retVal0)][clear_a(args)]; + + 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("};")) // + [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)] // + [assign_a(constructor, constructor0)]; } classic::rule const& start() const { @@ -113,8 +231,8 @@ struct ClassGrammar: public classic::grammar { }; // ClassGrammar -/* ************************************************************************* */ -TEST( wrap, Small ) { +//****************************************************************************** +TEST( Class, Grammar ) { using classic::space_p; @@ -122,13 +240,15 @@ TEST( wrap, Small ) { Class cls; ClassGrammar g(cls); + EXPECT(parse("class Point2 {\n};", g, space_p).full); + string markup( - string("class Point2 { \n") + - string(" double x() const; \n") + // Method 1 - string(" Matrix returnMatrix() const; \n") + // Method 2 - string(" Point2 returnPoint2() const; \n") + // Method 3 - string(" static Vector returnVector(); \n") + // Static Method 1 - string("};\n")); + string("class Point2 { \n") + + string(" double x() const; \n") // Method 1 + + string(" Matrix returnMatrix() const; \n") // Method 2 + + string(" Point2 returnPoint2() const; \n") // Method 3 + + string(" static Vector returnVector(); \n") // Static Method 1 + + string("};")); EXPECT(parse(markup.c_str(), g, space_p).full); From 0e48e2ff0b1a90c048b83f3e8891d212b634ba6c Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 12:41:35 +0100 Subject: [PATCH 06/13] Moved to header --- wrap/Class.h | 131 ++++++++++++++++++++++++++++++++++ wrap/tests/testClass.cpp | 149 --------------------------------------- 2 files changed, 131 insertions(+), 149 deletions(-) diff --git a/wrap/Class.h b/wrap/Class.h index 8faf7ab77..bc538fc7d 100644 --- a/wrap/Class.h +++ b/wrap/Class.h @@ -19,6 +19,7 @@ #pragma once +#include "spirit.h" #include "Template.h" #include "Constructor.h" #include "Deconstructor.h" @@ -26,6 +27,18 @@ #include "StaticMethod.h" #include "TypeAttributesTable.h" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif +#include +#include +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +namespace bl = boost::lambda; + #include #include #include @@ -145,5 +158,123 @@ private: void comment_fragment(FileWriter& proxyFile) const; }; +/* ************************************************************************* */ +// 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 + + /// Construct type grammar and specify where result is placed + ClassGrammar(Class& result) : + result_(result) { + } + + /// Definition of type grammar + template + struct definition: BasicRules { + + using BasicRules::name_p; + using BasicRules::className_p; + using BasicRules::comments_p; + + // NOTE: allows for pointers to all types + ArgumentList args; + ArgumentListGrammar argumentList_g; + + Constructor constructor0, constructor; + + ReturnValue retVal0, retVal; + ReturnValueGrammar returnValue_g; + + // template + Template methodTemplate, classTemplate; + TemplateGrammar methodTemplate_g, classTemplate_g; + + std::string methodName; + bool isConst, T, F; + + // Parent class + Qualified possibleParent; + TypeGrammar classParent_p; + + classic::rule templateList_p, constructor_p, methodName_p, + method_p, staticMethodName_p, static_method_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) { + + 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("::"); + + methodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; + + // gtsam::Values retract(const gtsam::VectorValues& delta) const; + method_p = !methodTemplate_g + >> (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::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)]; + + 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(methodName), bl::var(args), bl::var(retVal), boost::none, + verbose)] // + [assign_a(retVal, retVal0)][clear_a(args)]; + + 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("};")) // + [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)] // + [assign_a(constructor, constructor0)]; + } + + classic::rule const& start() const { + return class_p; + } + + }; +}; +// ClassGrammar + } // \namespace wrap diff --git a/wrap/tests/testClass.cpp b/wrap/tests/testClass.cpp index f3d2c14d1..1b7cfe31a 100644 --- a/wrap/tests/testClass.cpp +++ b/wrap/tests/testClass.cpp @@ -82,155 +82,6 @@ TEST( Class, TemplatedMethods ) { EXPECT(cls.exists(name+"Point3")); } -/* ************************************************************************* */ -#include "../Module.h" -#include "../FileWriter.h" -#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 - -#include -#include - -using namespace std; -using namespace wrap; -using namespace BOOST_SPIRIT_CLASSIC_NS; -namespace bl = boost::lambda; -namespace fs = boost::filesystem; - -// 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 - - /// Construct type grammar and specify where result is placed - ClassGrammar(Class& result) : - result_(result) { - } - - /// Definition of type grammar - template - struct definition: BasicRules { - - using BasicRules::name_p; - using BasicRules::className_p; - using BasicRules::comments_p; - - // NOTE: allows for pointers to all types - ArgumentList args; - ArgumentListGrammar argumentList_g; - - Constructor constructor0, constructor; - - ReturnValue retVal0, retVal; - ReturnValueGrammar returnValue_g; - - // template - Template methodTemplate, classTemplate; - TemplateGrammar methodTemplate_g, classTemplate_g; - - string methodName; - bool isConst, T, F; - - // Parent class - Qualified possibleParent; - TypeGrammar classParent_p; - - classic::rule templateList_p, constructor_p, methodName_p, - method_p, staticMethodName_p, static_method_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) { - - 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("::"); - - methodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; - - // gtsam::Values retract(const gtsam::VectorValues& delta) const; - method_p = !methodTemplate_g - >> (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::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)]; - - 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(methodName), bl::var(args), bl::var(retVal), boost::none, - verbose)] // - [assign_a(retVal, retVal0)][clear_a(args)]; - - 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("};")) // - [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)] // - [assign_a(constructor, constructor0)]; - } - - classic::rule const& start() const { - return class_p; - } - - }; -}; -// ClassGrammar - //****************************************************************************** TEST( Class, Grammar ) { From b8d7516e93eff1143f7e59a6fd133699c2f5c71f Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 13:12:21 +0100 Subject: [PATCH 07/13] 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); From 3606a1ab683a9d17a4d6365b5783ccfd45dd9995 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 13:30:21 +0100 Subject: [PATCH 08/13] killed old stuff --- wrap/tests/testMethod.cpp | 77 --------------------------------------- 1 file changed, 77 deletions(-) diff --git a/wrap/tests/testMethod.cpp b/wrap/tests/testMethod.cpp index 5b58fa31e..d823e9099 100644 --- a/wrap/tests/testMethod.cpp +++ b/wrap/tests/testMethod.cpp @@ -42,83 +42,6 @@ TEST( Method, addOverload ) { EXPECT_LONGS_EQUAL(2, method.nrOverloads()); } -//// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html -//struct method_grammar: public classic::grammar { -// -// wrap::Method& result_; ///< successful parse will be placed in here -// -// ArgumentList args; -// Argument arg0, arg; -// TypeGrammar argument_type_g; -// -// ReturnType retType0, retType; -// TypeGrammar returntype_g; -// -// ReturnValue retVal0, retVal; -// -// /// Construct type grammar and specify where result is placed -// method_grammar(wrap::Method& result) : -// result_(result), argument_type_g(arg.type), returntype_g(retType) { -// } -// -// /// Definition of type grammar -// template -// struct definition: basic_rules { -// -// Rule templateArgValue_p, templateArgValues_p, argument_p, argumentList_p, -// returnType1_p, returnType2_p, pair_p, returnValue_p, methodName_p, -// method_p; -// -// definition(method_grammar const& self) { -// -// using namespace wrap; -// using namespace classic; -// -//// Rule templateArgValue_p = type_grammar(self.templateArgValue); -//// -//// // template -//// Rule templateArgValues_p = (str_p("template") >> '<' >> name_p >> '=' -//// >> '{' >> !(templateArgValue_p >> *(',' >> templateArgValue_p)) >> '}' -//// >> '>'); -//// -// // Create type grammar that will place result in actual -// ArgumentList actual; -// ArgumentListGrammar g(actual); -// -// EXPECT(parse("(const gtsam::Point2& p4)", g, space_p).full); -// EXPECT_LONGS_EQUAL(1, actual.size()); -// actual.clear(); -// -// returnType1_p = self.returntype_g // -// [assign_a(self.retVal.type1, retType)] // -// [assign_a(self.retType, self.retType0)]; -// -// returnType2_p = self.returntype_g // -// [assign_a(self.retVal.type2, retType)] // -// [assign_a(self.retType, self.retType0)]; -// -// pair_p = (str_p("pair") >> '<' >> returnType1_p >> ',' >> returnType2_p -// >> '>')[assign_a(self.retVal.isPair, true)]; -// -// returnValue_p = pair_p | returnType1_p; -// -// methodName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; -// -// // gtsam::Values retract(const gtsam::VectorValues& delta) const; -// method_p = -//// !templateArgValues_p >> -// (returnValue_p >> methodName_p >> '(' >> argumentList_p >> ')' -// >> !str_p("const") >> ';' >> *basic_rules::comments_p); -// } -// -// Rule const& start() const { -// return method_p; -// } -// -// }; -//}; -//// method_grammar -// ////****************************************************************************** //TEST( Method, grammar ) { // From 04af29f7263df7cb928290952b064fd10856e648 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 13:30:36 +0100 Subject: [PATCH 09/13] Moved typedef --- wrap/GlobalFunction.h | 2 ++ wrap/Module.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wrap/GlobalFunction.h b/wrap/GlobalFunction.h index 4805231fb..f421e2f99 100644 --- a/wrap/GlobalFunction.h +++ b/wrap/GlobalFunction.h @@ -47,5 +47,7 @@ private: }; +typedef std::map GlobalFunctions; + } // \namespace wrap diff --git a/wrap/Module.h b/wrap/Module.h index e99e77bc9..e0c1b3f31 100644 --- a/wrap/Module.h +++ b/wrap/Module.h @@ -34,8 +34,6 @@ namespace wrap { */ struct Module { - typedef std::map GlobalFunctions; - // Filled during parsing: std::string name; ///< module name bool verbose; ///< verbose flag From 60d7b80055ff8a78190f83a10b308dc7ae7e7a56 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 13:30:52 +0100 Subject: [PATCH 10/13] Successful global function parser --- .cproject | 106 +++++++++++++++----------- wrap/tests/testGlobalFunction.cpp | 120 ++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 44 deletions(-) create mode 100644 wrap/tests/testGlobalFunction.cpp diff --git a/.cproject b/.cproject index 241afea81..bcf690995 100644 --- a/.cproject +++ b/.cproject @@ -592,6 +592,7 @@ make + tests/testBayesTree.run true false @@ -599,6 +600,7 @@ make + testBinaryBayesNet.run true false @@ -646,6 +648,7 @@ make + testSymbolicBayesNet.run true false @@ -653,6 +656,7 @@ make + tests/testSymbolicFactor.run true false @@ -660,6 +664,7 @@ make + testSymbolicFactorGraph.run true false @@ -675,6 +680,7 @@ make + tests/testBayesTree true false @@ -1122,6 +1128,7 @@ make + testErrors.run true false @@ -1351,6 +1358,46 @@ true true + + make + -j5 + testBTree.run + true + true + true + + + make + -j5 + testDSF.run + true + true + true + + + make + -j5 + testDSFMap.run + true + true + true + + + make + -j5 + testDSFVector.run + true + true + true + + + make + -j5 + testFixedVector.run + true + true + true + make -j2 @@ -1433,7 +1480,6 @@ make - testSimulated2DOriented.run true false @@ -1473,7 +1519,6 @@ make - testSimulated2D.run true false @@ -1481,7 +1526,6 @@ make - testSimulated3D.run true false @@ -1495,46 +1539,6 @@ true true - - make - -j5 - testBTree.run - true - true - true - - - make - -j5 - testDSF.run - true - true - true - - - make - -j5 - testDSFMap.run - true - true - true - - - make - -j5 - testDSFVector.run - true - true - true - - - make - -j5 - testFixedVector.run - true - true - true - make -j5 @@ -1792,6 +1796,7 @@ cpack + -G DEB true false @@ -1799,6 +1804,7 @@ cpack + -G RPM true false @@ -1806,6 +1812,7 @@ cpack + -G TGZ true false @@ -1813,6 +1820,7 @@ cpack + --config CPackSourceConfig.cmake true false @@ -2425,6 +2433,14 @@ true true + + make + -j4 + testGlobalFunction.run + true + true + true + make -j5 @@ -2659,6 +2675,7 @@ make + testGraph.run true false @@ -2666,6 +2683,7 @@ make + testJunctionTree.run true false @@ -2673,6 +2691,7 @@ make + testSymbolicBayesNetB.run true false @@ -3216,7 +3235,6 @@ make - tests/testGaussianISAM2 true false diff --git a/wrap/tests/testGlobalFunction.cpp b/wrap/tests/testGlobalFunction.cpp new file mode 100644 index 000000000..bd2159588 --- /dev/null +++ b/wrap/tests/testGlobalFunction.cpp @@ -0,0 +1,120 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file testMethod.cpp + * @brief Unit test for GlobalFunction class + * @author Frank Dellaert + * @date Nov 12, 2014 + **/ + +#include +#include +#include + +using namespace std; +using namespace wrap; + +//****************************************************************************** +// Constructor +TEST( GlobalFunction, Constructor ) { + GlobalFunction f; +} + +/* ************************************************************************* */ +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif +#include +#include +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +namespace bl = boost::lambda; +// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html +struct GlobalFunctionGrammar: public classic::grammar { + + GlobalFunctions& global_functions_; ///< successful parse will be placed in here + + /// Construct type grammar and specify where result is placed + GlobalFunctionGrammar(GlobalFunctions& global_functions) : + global_functions_(global_functions) { + } + + /// Definition of type grammar + template + struct definition: BasicRules { + +// using BasicRules::name_p; +// using BasicRules::className_p; + using BasicRules::comments_p; + + ArgumentList args; + ArgumentListGrammar argumentList_g; + + ReturnValue retVal0, retVal; + ReturnValueGrammar returnValue_g; + + Qualified globalFunction; + + classic::rule globalFunctionName_p, global_function_p; + + definition(GlobalFunctionGrammar const& self) : + argumentList_g(args), returnValue_g(retVal) { + + using namespace classic; + bool verbose = false; // TODO + + globalFunctionName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; + + // parse a global function + global_function_p = (returnValue_g + >> globalFunctionName_p[assign_a(globalFunction.name_)] + >> argumentList_g >> ';' >> *comments_p) // + [bl::bind(&GlobalFunction::addOverload, + bl::var(self.global_functions_)[bl::var(globalFunction.name_)], + bl::var(globalFunction), bl::var(args), bl::var(retVal), + boost::none, verbose)] // + [assign_a(retVal, retVal0)][clear_a(globalFunction)][clear_a(args)]; + + } + + classic::rule const& start() const { + return global_function_p; + } + + }; +}; +// GlobalFunctionGrammar + +//****************************************************************************** +TEST( GlobalFunction, Grammar ) { + + using classic::space_p; + + // Create type grammar that will place result in actual + GlobalFunctions actual; + GlobalFunctionGrammar g(actual); + + // a class type with namespaces + EXPECT(parse("Vector aGlobalFunction();", g, space_p).full); + EXPECT(parse("Vector overloadedGlobalFunction(int a);", g, space_p).full); + EXPECT(parse("Vector overloadedGlobalFunction(int a, double b);", g, space_p).full); +} + +//****************************************************************************** +int main() { + TestResult tr; + return TestRegistry::runAllTests(tr); +} +//****************************************************************************** From a8de6c4dc30700e9a6714956fb14c1939e67105d Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 13:41:46 +0100 Subject: [PATCH 11/13] Moved to header --- wrap/GlobalFunction.h | 69 +++++++++++++++++++++++++++++++ wrap/tests/testGlobalFunction.cpp | 69 +------------------------------ 2 files changed, 70 insertions(+), 68 deletions(-) diff --git a/wrap/GlobalFunction.h b/wrap/GlobalFunction.h index f421e2f99..d26ec8ae3 100644 --- a/wrap/GlobalFunction.h +++ b/wrap/GlobalFunction.h @@ -11,6 +11,18 @@ #include "FullyOverloadedFunction.h" +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif +#include +#include +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + +namespace bl = boost::lambda; + namespace wrap { struct GlobalFunction: public FullyOverloadedFunction { @@ -49,5 +61,62 @@ private: typedef std::map GlobalFunctions; +/* ************************************************************************* */ +// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html +struct GlobalFunctionGrammar: public classic::grammar { + + GlobalFunctions& global_functions_; ///< successful parse will be placed in here + + /// Construct type grammar and specify where result is placed + GlobalFunctionGrammar(GlobalFunctions& global_functions) : + global_functions_(global_functions) { + } + + /// Definition of type grammar + template + struct definition: BasicRules { + +// using BasicRules::name_p; +// using BasicRules::className_p; + using BasicRules::comments_p; + + ArgumentList args; + ArgumentListGrammar argumentList_g; + + ReturnValue retVal0, retVal; + ReturnValueGrammar returnValue_g; + + Qualified globalFunction; + + classic::rule globalFunctionName_p, global_function_p; + + definition(GlobalFunctionGrammar const& self) : + argumentList_g(args), returnValue_g(retVal) { + + using namespace classic; + bool verbose = false; // TODO + + globalFunctionName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; + + // parse a global function + global_function_p = (returnValue_g + >> globalFunctionName_p[assign_a(globalFunction.name_)] + >> argumentList_g >> ';' >> *comments_p) // + [bl::bind(&GlobalFunction::addOverload, + bl::var(self.global_functions_)[bl::var(globalFunction.name_)], + bl::var(globalFunction), bl::var(args), bl::var(retVal), + boost::none, verbose)] // + [assign_a(retVal, retVal0)][clear_a(globalFunction)][clear_a(args)]; + + } + + classic::rule const& start() const { + return global_function_p; + } + + }; +}; +// GlobalFunctionGrammar + } // \namespace wrap diff --git a/wrap/tests/testGlobalFunction.cpp b/wrap/tests/testGlobalFunction.cpp index bd2159588..b8ed67a0f 100644 --- a/wrap/tests/testGlobalFunction.cpp +++ b/wrap/tests/testGlobalFunction.cpp @@ -29,74 +29,6 @@ TEST( GlobalFunction, Constructor ) { GlobalFunction f; } -/* ************************************************************************* */ -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-variable" -#endif -#include -#include -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - -namespace bl = boost::lambda; -// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html -struct GlobalFunctionGrammar: public classic::grammar { - - GlobalFunctions& global_functions_; ///< successful parse will be placed in here - - /// Construct type grammar and specify where result is placed - GlobalFunctionGrammar(GlobalFunctions& global_functions) : - global_functions_(global_functions) { - } - - /// Definition of type grammar - template - struct definition: BasicRules { - -// using BasicRules::name_p; -// using BasicRules::className_p; - using BasicRules::comments_p; - - ArgumentList args; - ArgumentListGrammar argumentList_g; - - ReturnValue retVal0, retVal; - ReturnValueGrammar returnValue_g; - - Qualified globalFunction; - - classic::rule globalFunctionName_p, global_function_p; - - definition(GlobalFunctionGrammar const& self) : - argumentList_g(args), returnValue_g(retVal) { - - using namespace classic; - bool verbose = false; // TODO - - globalFunctionName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; - - // parse a global function - global_function_p = (returnValue_g - >> globalFunctionName_p[assign_a(globalFunction.name_)] - >> argumentList_g >> ';' >> *comments_p) // - [bl::bind(&GlobalFunction::addOverload, - bl::var(self.global_functions_)[bl::var(globalFunction.name_)], - bl::var(globalFunction), bl::var(args), bl::var(retVal), - boost::none, verbose)] // - [assign_a(retVal, retVal0)][clear_a(globalFunction)][clear_a(args)]; - - } - - classic::rule const& start() const { - return global_function_p; - } - - }; -}; -// GlobalFunctionGrammar - //****************************************************************************** TEST( GlobalFunction, Grammar ) { @@ -110,6 +42,7 @@ TEST( GlobalFunction, Grammar ) { EXPECT(parse("Vector aGlobalFunction();", g, space_p).full); EXPECT(parse("Vector overloadedGlobalFunction(int a);", g, space_p).full); EXPECT(parse("Vector overloadedGlobalFunction(int a, double b);", g, space_p).full); + LONGS_EQUAL(2,actual.size()); } //****************************************************************************** From 41d2783beba19e6d78b63a155e181f3daf84c1d3 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 13:49:25 +0100 Subject: [PATCH 12/13] GlobalFunctionGrammar done and used --- wrap/GlobalFunction.h | 11 +++++++---- wrap/Module.cpp | 30 ++++-------------------------- wrap/tests/testGlobalFunction.cpp | 3 ++- 3 files changed, 13 insertions(+), 31 deletions(-) diff --git a/wrap/GlobalFunction.h b/wrap/GlobalFunction.h index d26ec8ae3..b2a582654 100644 --- a/wrap/GlobalFunction.h +++ b/wrap/GlobalFunction.h @@ -66,10 +66,12 @@ typedef std::map GlobalFunctions; struct GlobalFunctionGrammar: public classic::grammar { GlobalFunctions& global_functions_; ///< successful parse will be placed in here + std::vector& namespaces_; /// Construct type grammar and specify where result is placed - GlobalFunctionGrammar(GlobalFunctions& global_functions) : - global_functions_(global_functions) { + GlobalFunctionGrammar(GlobalFunctions& global_functions, + std::vector& namespaces) : + global_functions_(global_functions), namespaces_(namespaces) { } /// Definition of type grammar @@ -102,7 +104,8 @@ struct GlobalFunctionGrammar: public classic::grammar { global_function_p = (returnValue_g >> globalFunctionName_p[assign_a(globalFunction.name_)] >> argumentList_g >> ';' >> *comments_p) // - [bl::bind(&GlobalFunction::addOverload, + [assign_a(globalFunction.namespaces_, self.namespaces_)][bl::bind( + &GlobalFunction::addOverload, bl::var(self.global_functions_)[bl::var(globalFunction.name_)], bl::var(globalFunction), bl::var(args), bl::var(retVal), boost::none, verbose)] // @@ -118,5 +121,5 @@ struct GlobalFunctionGrammar: public classic::grammar { }; // GlobalFunctionGrammar -} // \namespace wrap +}// \namespace wrap diff --git a/wrap/Module.cpp b/wrap/Module.cpp index 907ad1472..55fd13715 100644 --- a/wrap/Module.cpp +++ b/wrap/Module.cpp @@ -126,30 +126,8 @@ void Module::parseMarkup(const std::string& data) { [push_back_a(templateInstantiationTypedefs, singleInstantiation)] [assign_a(singleInstantiation, singleInstantiation0)]; - // NOTE: allows for pointers to all types - ArgumentList args; - ArgumentListGrammar argumentList_g(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 globalFunctionName_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')]; - - // parse a global function - Qualified globalFunction; - Rule global_function_p = - (returnValue_g >> globalFunctionName_p[assign_a(globalFunction.name_)] >> - argumentList_g >> ';' >> *basic.comments_p) - [assign_a(globalFunction.namespaces_,namespaces)] - [bl::bind(&GlobalFunction::addOverload, - bl::var(global_functions)[bl::var(globalFunction.name_)], - bl::var(globalFunction), bl::var(args), bl::var(retVal), boost::none,verbose)] - [assign_a(retVal,retVal0)] - [clear_a(globalFunction)] - [clear_a(args)]; + // Create grammar for global functions + GlobalFunctionGrammar global_function_g(global_functions,namespaces); Rule include_p = str_p("#include") >> ch_p('<') >> (*(anychar_p - '>'))[push_back_a(includes)] >> ch_p('>'); @@ -162,7 +140,7 @@ void Module::parseMarkup(const std::string& data) { (str_p("namespace") >> basic.namespace_p[push_back_a(namespaces)] >> ch_p('{') - >> *(include_p | class_p | templateSingleInstantiation_p | global_function_p | namespace_def_p | basic.comments_p) + >> *(include_p | class_p | templateSingleInstantiation_p | global_function_g | namespace_def_p | basic.comments_p) >> ch_p('}')) [pop_a(namespaces)]; @@ -182,7 +160,7 @@ void Module::parseMarkup(const std::string& data) { Rule module_content_p = basic.comments_p | include_p | class_p | templateSingleInstantiation_p | forward_declaration_p - | global_function_p | namespace_def_p; + | global_function_g | namespace_def_p; Rule module_p = *module_content_p >> !end_p; diff --git a/wrap/tests/testGlobalFunction.cpp b/wrap/tests/testGlobalFunction.cpp index b8ed67a0f..32ab5dafb 100644 --- a/wrap/tests/testGlobalFunction.cpp +++ b/wrap/tests/testGlobalFunction.cpp @@ -36,7 +36,8 @@ TEST( GlobalFunction, Grammar ) { // Create type grammar that will place result in actual GlobalFunctions actual; - GlobalFunctionGrammar g(actual); + vector namespaces; + GlobalFunctionGrammar g(actual,namespaces); // a class type with namespaces EXPECT(parse("Vector aGlobalFunction();", g, space_p).full); From afebf2087f140fd17beed582f9450433c7e64be2 Mon Sep 17 00:00:00 2001 From: dellaert Date: Tue, 2 Dec 2014 14:12:22 +0100 Subject: [PATCH 13/13] Small problem w virtual --- wrap/Class.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrap/Class.h b/wrap/Class.h index 8072c50f6..f4c687eca 100644 --- a/wrap/Class.h +++ b/wrap/Class.h @@ -256,7 +256,7 @@ struct ClassGrammar: public classic::grammar { // parse a full class 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("virtual")[assign_a(self.cls_.isVirtual, T)]) >> str_p("class") >> className_p[assign_a(self.cls_.name_)] >> (classParent_p | '{') >> // *(functions_p | comments_p) >> str_p("};")) //