| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | /* ----------------------------------------------------------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  * -------------------------------------------------------------------------- */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							| 
									
										
										
										
											2011-10-14 11:23:14 +08:00
										 |  |  |  * @file testSpirit.cpp | 
					
						
							|  |  |  |  * @brief Unit test for Boost's awesome Spirit parser | 
					
						
							|  |  |  |  * @author Frank Dellaert | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  |  **/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <boost/spirit/include/classic_core.hpp>
 | 
					
						
							|  |  |  | #include <boost/spirit/include/classic_push_back_actor.hpp>
 | 
					
						
							|  |  |  | #include <CppUnitLite/TestHarness.h>
 | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  | #include <wrap/utilities.h>
 | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | using namespace BOOST_SPIRIT_CLASSIC_NS; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | typedef rule<BOOST_SPIRIT_CLASSIC_NS::phrase_scanner_t> Rule; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | // lexeme_d turns off white space skipping
 | 
					
						
							|  |  |  | // http://www.boost.org/doc/libs/1_37_0/libs/spirit/classic/doc/directives.html
 | 
					
						
							|  |  |  | Rule name_p       = lexeme_d[alpha_p >> *(alnum_p | '_')]; | 
					
						
							|  |  |  | Rule className_p  = lexeme_d[upper_p >> *(alnum_p | '_')]; | 
					
						
							|  |  |  | Rule methodName_p = lexeme_d[lower_p >> *(alnum_p | '_')]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Rule basisType_p = (str_p("string") | "bool" | "size_t" | "int" | "double" | "Vector" | "Matrix"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( spirit, real ) { | 
					
						
							|  |  |  |   // check if we can parse 8.99 as a real
 | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(parse("8.99", real_p, space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  |   // make sure parsing fails on this one
 | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(!parse("zztop", real_p, space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( spirit, string ) { | 
					
						
							|  |  |  |   // check if we can parse a string
 | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(parse("double", str_p("double"), space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( spirit, sequence ) { | 
					
						
							|  |  |  |   // check that we skip white space
 | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(parse("int int", str_p("int") >> *str_p("int"), space_p).full); | 
					
						
							|  |  |  |   EXPECT(parse("int --- - -- -", str_p("int") >> *ch_p('-'), space_p).full); | 
					
						
							|  |  |  |   EXPECT(parse("const \t string", str_p("const") >> str_p("string"), space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-02 02:57:32 +08:00
										 |  |  |   // note that (see spirit FAQ) the vanilla rule<> does not deal with whitespace
 | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  |   rule<>vanilla_p = str_p("const") >> str_p("string"); | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(!parse("const \t string", vanilla_p, space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // to fix it, we need to use <phrase_scanner_t>
 | 
					
						
							|  |  |  |   rule<phrase_scanner_t>phrase_level_p = str_p("const") >> str_p("string"); | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(parse("const \t string", phrase_level_p, space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | // parser for interface files
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // const string reference reference
 | 
					
						
							|  |  |  | Rule constStringRef_p =  | 
					
						
							|  |  |  |   str_p("const") >> "string" >> '&'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // class reference
 | 
					
						
							|  |  |  | Rule classRef_p = className_p >> '&'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // const class reference
 | 
					
						
							|  |  |  | Rule constClassRef_p = str_p("const") >> classRef_p; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // method parsers
 | 
					
						
							|  |  |  | Rule constMethod_p = basisType_p >> methodName_p >> '(' >> ')' >> "const" >> ';'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( spirit, basisType_p ) { | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(!parse("Point3", basisType_p, space_p).full); | 
					
						
							|  |  |  |   EXPECT(parse("string", basisType_p, space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( spirit, className_p ) { | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(parse("Point3", className_p, space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( spirit, classRef_p ) { | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(parse("Point3 &", classRef_p, space_p).full); | 
					
						
							|  |  |  |   EXPECT(parse("Point3&", classRef_p, space_p).full); | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( spirit, constMethod_p ) { | 
					
						
							| 
									
										
										
										
											2011-12-02 06:06:03 +08:00
										 |  |  |   EXPECT(parse("double norm() const;", constMethod_p, space_p).full); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-12-07 11:05:37 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | TEST( spirit, return_value_p ) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   bool isEigen = true; | 
					
						
							|  |  |  |   string actual_return_type; | 
					
						
							|  |  |  |   string actual_function_name; | 
					
						
							| 
									
										
										
										
											2011-12-07 11:05:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Rule basisType_p = | 
					
						
							|  |  |  |     (str_p("string") | "bool" | "size_t" | "int" | "double"); | 
					
						
							| 
									
										
										
										
											2011-12-07 11:05:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Rule eigenType_p = | 
					
						
							|  |  |  |     (str_p("Vector") | "Matrix"); | 
					
						
							| 
									
										
										
										
											2011-12-07 11:05:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Rule className_p  = lexeme_d[upper_p >> *(alnum_p | '_')] - eigenType_p - basisType_p; | 
					
						
							| 
									
										
										
										
											2011-12-07 11:05:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Rule funcName_p  = lexeme_d[lower_p >> *(alnum_p | '_')]; | 
					
						
							| 
									
										
										
										
											2011-12-07 11:05:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Rule returnType_p = | 
					
						
							|  |  |  |       (basisType_p[assign_a(actual_return_type)][assign_a(isEigen, true)]) | | 
					
						
							|  |  |  |       (className_p[assign_a(actual_return_type)][assign_a(isEigen,false)]) | | 
					
						
							|  |  |  |       (eigenType_p[assign_a(actual_return_type)][assign_a(isEigen, true)]); | 
					
						
							| 
									
										
										
										
											2011-12-07 11:05:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Rule testFunc_p = returnType_p >> funcName_p[assign_a(actual_function_name)] >> str_p("();"); | 
					
						
							| 
									
										
										
										
											2011-12-07 11:05:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(parse("VectorNotEigen doesNotReturnAnEigenVector();", testFunc_p, space_p).full); | 
					
						
							|  |  |  |   EXPECT(!isEigen); | 
					
						
							|  |  |  |   EXPECT(actual_return_type == "VectorNotEigen"); | 
					
						
							|  |  |  |   EXPECT(actual_function_name == "doesNotReturnAnEigenVector"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   EXPECT(parse("Vector actuallyAVector();", testFunc_p, space_p).full); | 
					
						
							|  |  |  |   EXPECT(isEigen); | 
					
						
							|  |  |  |   EXPECT(actual_return_type == "Vector"); | 
					
						
							|  |  |  |   EXPECT(actual_function_name == "actuallyAVector"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-14 02:41:56 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | int main() { TestResult tr; return TestRegistry::runAllTests(tr); } | 
					
						
							|  |  |  | /* ************************************************************************* */ |