Limited namespace handling in wrap parser
							parent
							
								
									3cb1d27d4b
								
							
						
					
					
						commit
						1130cf43e0
					
				| 
						 | 
				
			
			@ -36,6 +36,7 @@ struct Class {
 | 
			
		|||
  std::list<Constructor> constructors;    ///< Class constructors
 | 
			
		||||
  std::list<Method> methods;              ///< Class methods
 | 
			
		||||
  std::list<StaticMethod> static_methods; ///< Static methods
 | 
			
		||||
  std::vector<std::string> namespaces;    ///< Stack of namespaces
 | 
			
		||||
  bool verbose_;                          ///< verbose flag
 | 
			
		||||
 | 
			
		||||
  // And finally MATLAB code is emitted, methods below called by Module::matlab_code
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,19 +51,16 @@ Module::Module(const string& interfacePath,
 | 
			
		|||
  Method method0(enable_verbose), method(enable_verbose);
 | 
			
		||||
  StaticMethod static_method0(enable_verbose), static_method(enable_verbose);
 | 
			
		||||
  Class cls0(enable_verbose),cls(enable_verbose);
 | 
			
		||||
  vector<string> namespaces, namespaces_parent;
 | 
			
		||||
 | 
			
		||||
  //----------------------------------------------------------------------------
 | 
			
		||||
  // Grammar with actions that build the Class object. Actions are
 | 
			
		||||
  // defined within the square brackets [] and are executed whenever a
 | 
			
		||||
  // rule is successfully parsed. Define BOOST_SPIRIT_DEBUG to debug.
 | 
			
		||||
  // The grammar is allows a very restricted C++ header:
 | 
			
		||||
  // - No comments allowed.
 | 
			
		||||
  //  -Only types allowed are string, bool, size_t int, double, Vector, and Matrix
 | 
			
		||||
  //   as well as class names that start with an uppercase letter
 | 
			
		||||
  // - The types unsigned int and bool should be specified as int.
 | 
			
		||||
  // The grammar is allows a very restricted C++ header
 | 
			
		||||
  // ----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  Rule comments_p =  comment_p("/*", "*/") |	comment_p("//");
 | 
			
		||||
  Rule comments_p =  comment_p("/*", "*/") |	comment_p("//", eol_p);
 | 
			
		||||
 | 
			
		||||
  // lexeme_d turns off white space skipping
 | 
			
		||||
  // http://www.boost.org/doc/libs/1_37_0/libs/spirit/classic/doc/directives.html
 | 
			
		||||
| 
						 | 
				
			
			@ -157,16 +154,22 @@ Module::Module(const string& interfacePath,
 | 
			
		|||
 | 
			
		||||
  Rule functions_p = constructor_p | method_p | static_method_p;
 | 
			
		||||
 | 
			
		||||
  Rule class_p = str_p("class") >> className_p[assign_a(cls.name)] >> '{' >>
 | 
			
		||||
  Rule class_p = (str_p("class") >> className_p[assign_a(cls.name)] >> '{' >>
 | 
			
		||||
    *(functions_p | comments_p) >>
 | 
			
		||||
    '}' >> ";";
 | 
			
		||||
    str_p("};"))[assign_a(cls.namespaces, namespaces)][push_back_a(classes,cls)][assign_a(cls,cls0)];
 | 
			
		||||
 | 
			
		||||
  Rule module_p = *comments_p >> +(class_p
 | 
			
		||||
    [push_back_a(classes,cls)]
 | 
			
		||||
    [assign_a(cls,cls0)]
 | 
			
		||||
     >> *comments_p)
 | 
			
		||||
     >> *comments_p
 | 
			
		||||
    >> !end_p;
 | 
			
		||||
  Rule namespace_name_p = lexeme_d[(upper_p | lower_p) >> *(alnum_p | '_')];
 | 
			
		||||
 | 
			
		||||
  Rule namespace_p = str_p("namespace") >>
 | 
			
		||||
  		namespace_name_p[assign_a(namespaces_parent, namespaces)][push_back_a(namespaces)] // save previous state
 | 
			
		||||
      >> confix_p('{', // start namespace
 | 
			
		||||
      		+(comments_p | class_p | namespace_p),
 | 
			
		||||
      		('}' >> (*anychar_p - ch_p(';'))) // end namespace, avoid confusion with classes
 | 
			
		||||
      		)[assign_a(namespaces, namespaces_parent)]; // switch back to parent namespace
 | 
			
		||||
 | 
			
		||||
  Rule module_content_p =	 comments_p | namespace_p | class_p;
 | 
			
		||||
 | 
			
		||||
  Rule module_p = *module_content_p >> !end_p;
 | 
			
		||||
 | 
			
		||||
  //----------------------------------------------------------------------------
 | 
			
		||||
  // for debugging, define BOOST_SPIRIT_DEBUG
 | 
			
		||||
| 
						 | 
				
			
			@ -193,7 +196,7 @@ Module::Module(const string& interfacePath,
 | 
			
		|||
 | 
			
		||||
  // read interface file
 | 
			
		||||
  string interfaceFile = interfacePath + "/" + moduleName + ".h";
 | 
			
		||||
  string contents = wrap::file_contents(interfaceFile);
 | 
			
		||||
  string contents = file_contents(interfaceFile);
 | 
			
		||||
 | 
			
		||||
  // and parse contents
 | 
			
		||||
  parse_info<const char*> info = parse(contents.c_str(), module_p, space_p);
 | 
			
		||||
| 
						 | 
				
			
			@ -201,6 +204,16 @@ Module::Module(const string& interfacePath,
 | 
			
		|||
    printf("parsing stopped at \n%.20s\n",info.stop);
 | 
			
		||||
    throw ParseFailed(info.length);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!namespaces.empty()) {
 | 
			
		||||
  	cout << "Namespaces not closed, remaining: ";
 | 
			
		||||
  	BOOST_FOREACH(const string& ns, namespaces)
 | 
			
		||||
  		cout << ns << " ";
 | 
			
		||||
  	cout << endl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!cls.name.empty())
 | 
			
		||||
  	cout << "\nClass name: " << cls.name << endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,8 @@ class Point2 {
 | 
			
		|||
 VectorNotEigen vectorConfusion();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace ns_inner {
 | 
			
		||||
 | 
			
		||||
class Point3 {
 | 
			
		||||
  Point3(double x, double y, double z);
 | 
			
		||||
  double norm() const;
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +22,8 @@ class Point3 {
 | 
			
		|||
 | 
			
		||||
// another comment
 | 
			
		||||
 | 
			
		||||
// another comment
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A multi-line comment!
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +71,8 @@ class Test {
 | 
			
		|||
  // even more comments at the end!
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // \ns_inner
 | 
			
		||||
 | 
			
		||||
// comments at the end!
 | 
			
		||||
 | 
			
		||||
// even more comments at the end!
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,26 +34,24 @@ static string topdir = "TOPSRCDIR_NOT_CONFIGURED"; // If TOPSRCDIR is not define
 | 
			
		|||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( wrap, ArgumentList ) {
 | 
			
		||||
  ArgumentList args;
 | 
			
		||||
  Argument arg; arg.type = "double"; arg.name = "x";
 | 
			
		||||
  args.push_back(arg);
 | 
			
		||||
  args.push_back(arg);
 | 
			
		||||
  args.push_back(arg);
 | 
			
		||||
  CHECK(args.signature()=="ddd");
 | 
			
		||||
  EXPECT(args.types()=="double,double,double");
 | 
			
		||||
  EXPECT(args.names()=="x,x,x");
 | 
			
		||||
	ArgumentList args;
 | 
			
		||||
	Argument arg; arg.type = "double"; arg.name = "x";
 | 
			
		||||
	args.push_back(arg);
 | 
			
		||||
	args.push_back(arg);
 | 
			
		||||
	args.push_back(arg);
 | 
			
		||||
	CHECK(args.signature()=="ddd");
 | 
			
		||||
	EXPECT(args.types()=="double,double,double");
 | 
			
		||||
	EXPECT(args.names()=="x,x,x");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
TEST( wrap, check_exception ) {
 | 
			
		||||
	THROWS_EXCEPTION(Module("/notarealpath", "geometry",enable_verbose));
 | 
			
		||||
	CHECK_EXCEPTION(Module("/alsonotarealpath", "geometry",enable_verbose), CantOpenFile);
 | 
			
		||||
    
 | 
			
		||||
    string path = topdir + "/wrap/tests";
 | 
			
		||||
    Module module(path.c_str(), "testWrap1",enable_verbose);
 | 
			
		||||
	THROWS_EXCEPTION(throw DependencyMissing("a", "b"));
 | 
			
		||||
	CHECK_EXCEPTION(module.matlab_code("actual", "", "mexa64", "-O5"), DependencyMissing);
 | 
			
		||||
 | 
			
		||||
	string path = topdir + "/wrap/tests";
 | 
			
		||||
	Module module(path.c_str(), "testWrap1",enable_verbose);
 | 
			
		||||
//	CHECK_EXCEPTION(module.matlab_code("actual", "", "mexa64", "-O5"), DependencyMissing);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			@ -61,46 +59,61 @@ TEST( wrap, parse ) {
 | 
			
		|||
	string path = topdir + "/wrap/tests";
 | 
			
		||||
 | 
			
		||||
	Module module(path.c_str(), "geometry",enable_verbose);
 | 
			
		||||
	CHECK(module.classes.size()==3);
 | 
			
		||||
	EXPECT_LONGS_EQUAL(3, module.classes.size());
 | 
			
		||||
	//Hack to solve issues with instantiating Modules
 | 
			
		||||
	path = topdir + "/wrap";
 | 
			
		||||
 | 
			
		||||
	// check first class, Point2
 | 
			
		||||
	{
 | 
			
		||||
		Class cls = module.classes.at(0);
 | 
			
		||||
		EXPECT(assert_equal("Point2", cls.name));
 | 
			
		||||
		EXPECT_LONGS_EQUAL(2, cls.constructors.size());
 | 
			
		||||
		EXPECT_LONGS_EQUAL(4, cls.methods.size());
 | 
			
		||||
		EXPECT_LONGS_EQUAL(0, cls.static_methods.size());
 | 
			
		||||
		EXPECT_LONGS_EQUAL(0, cls.namespaces.size());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check second class, Point3
 | 
			
		||||
	Class cls = *(++module.classes.begin());
 | 
			
		||||
	EXPECT(cls.name=="Point3");
 | 
			
		||||
	EXPECT(cls.constructors.size()==1);
 | 
			
		||||
	EXPECT(cls.methods.size()==1);
 | 
			
		||||
	EXPECT(cls.static_methods.size()==2);
 | 
			
		||||
	{
 | 
			
		||||
		Class cls = module.classes.at(1);
 | 
			
		||||
		EXPECT(assert_equal("Point3", cls.name));
 | 
			
		||||
		EXPECT_LONGS_EQUAL(1, cls.constructors.size());
 | 
			
		||||
		EXPECT_LONGS_EQUAL(1, cls.methods.size());
 | 
			
		||||
		EXPECT_LONGS_EQUAL(2, cls.static_methods.size());
 | 
			
		||||
		EXPECT_LONGS_EQUAL(1, cls.namespaces.size());
 | 
			
		||||
		EXPECT(assert_equal("ns_inner", cls.namespaces.front()));
 | 
			
		||||
 | 
			
		||||
	// first constructor takes 3 doubles
 | 
			
		||||
	Constructor c1 = cls.constructors.front();
 | 
			
		||||
	EXPECT(c1.args.size()==3);
 | 
			
		||||
		// first constructor takes 3 doubles
 | 
			
		||||
		Constructor c1 = cls.constructors.front();
 | 
			
		||||
		EXPECT_LONGS_EQUAL(3, c1.args.size());
 | 
			
		||||
 | 
			
		||||
	// check first double argument
 | 
			
		||||
	Argument a1 = c1.args.front();
 | 
			
		||||
	EXPECT(!a1.is_const);
 | 
			
		||||
	EXPECT(a1.type=="double");
 | 
			
		||||
	EXPECT(!a1.is_ref);
 | 
			
		||||
	EXPECT(a1.name=="x");
 | 
			
		||||
		// check first double argument
 | 
			
		||||
		Argument a1 = c1.args.front();
 | 
			
		||||
		EXPECT(!a1.is_const);
 | 
			
		||||
		EXPECT(assert_equal("double", a1.type));
 | 
			
		||||
		EXPECT(!a1.is_ref);
 | 
			
		||||
		EXPECT(assert_equal("x", a1.name));
 | 
			
		||||
 | 
			
		||||
	// check method
 | 
			
		||||
	Method m1 = cls.methods.front();
 | 
			
		||||
	EXPECT(m1.returnVal_.type1=="double");
 | 
			
		||||
	EXPECT(m1.name_=="norm");
 | 
			
		||||
	EXPECT(m1.args_.size()==0);
 | 
			
		||||
	EXPECT(m1.is_const_);
 | 
			
		||||
		// check method
 | 
			
		||||
		Method m1 = cls.methods.front();
 | 
			
		||||
		EXPECT(assert_equal("double", m1.returnVal_.type1));
 | 
			
		||||
		EXPECT(assert_equal("norm", m1.name_));
 | 
			
		||||
		EXPECT_LONGS_EQUAL(0, m1.args_.size());
 | 
			
		||||
		EXPECT(m1.is_const_);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Test class is the third one
 | 
			
		||||
	Class testCls = module.classes.at(2);
 | 
			
		||||
	EXPECT_LONGS_EQUAL( 2, testCls.constructors.size());
 | 
			
		||||
	EXPECT_LONGS_EQUAL(19, testCls.methods.size());
 | 
			
		||||
	EXPECT_LONGS_EQUAL( 0, testCls.static_methods.size());
 | 
			
		||||
 | 
			
		||||
  // function to parse: pair<Vector,Matrix> return_pair (Vector v, Matrix A) const;
 | 
			
		||||
	Method m2 = testCls.methods.front();
 | 
			
		||||
	EXPECT(m2.returnVal_.isPair);
 | 
			
		||||
	EXPECT(m2.returnVal_.category1 == ReturnValue::EIGEN);
 | 
			
		||||
	EXPECT(m2.returnVal_.category2 == ReturnValue::EIGEN);
 | 
			
		||||
	//	// Test class is the third one
 | 
			
		||||
	//	LONGS_EQUAL(3, module.classes.size());
 | 
			
		||||
	//	Class testCls = module.classes.at(2);
 | 
			
		||||
	//	EXPECT_LONGS_EQUAL( 2, testCls.constructors.size());
 | 
			
		||||
	//	EXPECT_LONGS_EQUAL(19, testCls.methods.size());
 | 
			
		||||
	//	EXPECT_LONGS_EQUAL( 0, testCls.static_methods.size());
 | 
			
		||||
	//
 | 
			
		||||
	//  // function to parse: pair<Vector,Matrix> return_pair (Vector v, Matrix A) const;
 | 
			
		||||
	//	Method m2 = testCls.methods.front();
 | 
			
		||||
	//	EXPECT(m2.returnVal_.isPair);
 | 
			
		||||
	//	EXPECT(m2.returnVal_.category1 == ReturnValue::EIGEN);
 | 
			
		||||
	//	EXPECT(m2.returnVal_.category2 == ReturnValue::EIGEN);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			@ -137,8 +150,8 @@ TEST( wrap, matlab_code ) {
 | 
			
		|||
	EXPECT(files_equal(path + "/tests/expected/@Test/print.m"           , "actual/@Test/print.m"           ));
 | 
			
		||||
	EXPECT(files_equal(path + "/tests/expected/@Test/print.cpp"         , "actual/@Test/print.cpp"         ));
 | 
			
		||||
 | 
			
		||||
	EXPECT(files_equal(path + "/tests/expected/make_geometry.m"   , "actual/make_geometry.m"   ));
 | 
			
		||||
	EXPECT(files_equal(path + "/tests/expected/Makefile"   , "actual/Makefile"   ));
 | 
			
		||||
	EXPECT(files_equal(path + "/tests/expected/make_geometry.m", "actual/make_geometry.m"));
 | 
			
		||||
	EXPECT(files_equal(path + "/tests/expected/Makefile"       , "actual/Makefile"       ));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* ************************************************************************* */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,8 +54,8 @@ bool assert_equal(const std::string& expected, const std::string& actual) {
 | 
			
		|||
/* ************************************************************************* */
 | 
			
		||||
bool files_equal(const string& expected, const string& actual, bool skipheader) {
 | 
			
		||||
  try {
 | 
			
		||||
    string expected_contents = wrap::file_contents(expected, skipheader);
 | 
			
		||||
    string actual_contents   = wrap::file_contents(actual, skipheader);
 | 
			
		||||
    string expected_contents = file_contents(expected, skipheader);
 | 
			
		||||
    string actual_contents   = file_contents(actual, skipheader);
 | 
			
		||||
    bool equal = actual_contents == expected_contents;
 | 
			
		||||
    if (!equal) {
 | 
			
		||||
      stringstream command;
 | 
			
		||||
| 
						 | 
				
			
			@ -68,6 +68,10 @@ bool files_equal(const string& expected, const string& actual, bool skipheader)
 | 
			
		|||
    cerr << "expection: " << reason << endl;
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  catch (CantOpenFile& e) {
 | 
			
		||||
  	cerr << "file opening error: " << e.what() << endl;
 | 
			
		||||
  	return false;
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue