From: <gsa...@us...> - 2010-11-10 16:56:34
|
Revision: 148 http://dsim.svn.sourceforge.net/dsim/?rev=148&view=rev Author: gsabatier Date: 2010-11-10 16:56:23 +0000 (Wed, 10 Nov 2010) Log Message: ----------- [test/boostQi] to be continued. Modified Paths: -------------- trunk/dsim/test/boost/spirit/Makefile.am trunk/dsim/test/boost/spirit/schedule_parser.cpp trunk/dsim/test/boost/spirit/world_schedule.csv Added Paths: ----------- trunk/dsim/test/boost/spirit/action_parser trunk/dsim/test/boost/spirit/action_parser.cpp trunk/dsim/test/boost/spirit/bad_input.csv trunk/dsim/test/boost/spirit/complex_parser trunk/dsim/test/boost/spirit/complex_parser.cpp trunk/dsim/test/boost/spirit/employee_parser trunk/dsim/test/boost/spirit/employee_parser.cpp trunk/dsim/test/boost/spirit/good_input.csv trunk/dsim/test/boost/spirit/num_list1_parser trunk/dsim/test/boost/spirit/num_list1_parser.cpp trunk/dsim/test/boost/spirit/roman_parser trunk/dsim/test/boost/spirit/roman_parser.cpp trunk/dsim/test/boost/spirit/stream_iterator_parser trunk/dsim/test/boost/spirit/stream_iterator_parser.cpp trunk/dsim/test/boost/spirit/sum_parser trunk/dsim/test/boost/spirit/sum_parser.cpp Modified: trunk/dsim/test/boost/spirit/Makefile.am =================================================================== --- trunk/dsim/test/boost/spirit/Makefile.am 2010-11-02 17:47:57 UTC (rev 147) +++ trunk/dsim/test/boost/spirit/Makefile.am 2010-11-10 16:56:23 UTC (rev 148) @@ -3,44 +3,38 @@ MAINTAINERCLEANFILES = Makefile.in -check_PROGRAMS = full_calculator functor_parser number_parser \ - parameter_parser spirit_parser subrule_parser \ - schedule_parser search_string_parser levenshtein +check_PROGRAMS = employee_parser action_parser complex_parser \ + num_list1_parser roman_parser sum_parser \ + schedule_parser stream_iterator_parser levenshtein -full_calculator_SOURCES = full_calculator.cpp -full_calculator_CXXFLAGS = $(BOOST_CFLAGS) -full_calculator_LDADD = $(BOOST_LIBS) +employee_parser_SOURCES = employee_parser.cpp +employee_parser_CXXFLAGS = $(BOOST_CFLAGS) +employee_parser_LDADD = $(BOOST_LIBS) -functor_parser_SOURCES = functor_parser.cpp -functor_parser_CXXFLAGS = $(BOOST_CFLAGS) -functor_parser_LDADD = $(BOOST_LIBS) +action_parser_SOURCES = action_parser.cpp +action_parser_CXXFLAGS = $(BOOST_CFLAGS) +action_parser_LDADD = $(BOOST_LIBS) -number_parser_SOURCES = number_parser.cpp -number_parser_CXXFLAGS = $(BOOST_CFLAGS) -number_parser_LDADD = $(BOOST_LIBS) +complex_parser_SOURCES = complex_parser.cpp +complex_parser_CXXFLAGS = $(BOOST_CFLAGS) +complex_parser_LDADD = $(BOOST_LIBS) -parameter_parser_SOURCES = parameter_parser.cpp -parameter_parser_CXXFLAGS = $(BOOST_CFLAGS) -parameter_parser_LDADD = $(BOOST_LIBS) +num_list1_parser_SOURCES = num_list1_parser.cpp +num_list1_parser_CXXFLAGS = $(BOOST_CFLAGS) +num_list1_parser_LDADD = $(BOOST_LIBS) -spirit_parser_SOURCES = spirit_parser.cpp -spirit_parser_CXXFLAGS = $(BOOST_CFLAGS) -spirit_parser_LDADD = $(BOOST_LIBS) +roman_parser_SOURCES = roman_parser.cpp +roman_parser_CXXFLAGS = $(BOOST_CFLAGS) +roman_parser_LDADD = $(BOOST_LIBS) -subrule_parser_SOURCES = subrule_parser.cpp -subrule_parser_CXXFLAGS = $(BOOST_CFLAGS) -subrule_parser_LDADD = $(BOOST_LIBS) +sum_parser_SOURCES = sum_parser.cpp +sum_parser_CXXFLAGS = $(BOOST_CFLAGS) +sum_parser_LDADD = $(BOOST_LIBS) schedule_parser_SOURCES = schedule_parser.cpp schedule_parser_CXXFLAGS = $(BOOST_CFLAGS) schedule_parser_LDADD = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) -search_string_parser_SOURCES = search_string_parser.cpp -search_string_parser_CXXFLAGS = $(BOOST_CFLAGS) -search_string_parser_LDADD = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) - -levenshtein_SOURCES = levenshtein.cpp -levenshtein_LDADD = - -EXTRA_DIST = test_full_calculator.sh test_parameter_parser.sh \ - test_schedule_parser.sh +stream_iterator_parser_SOURCES = stream_iterator_parser.cpp +stream_iterator_parser_CXXFLAGS = $(BOOST_CFLAGS) +stream_iterator_parser_LDADD = $(BOOST_LIBS) $(BOOST_DATE_TIME_LIB) Added: trunk/dsim/test/boost/spirit/action_parser =================================================================== (Binary files differ) Property changes on: trunk/dsim/test/boost/spirit/action_parser ___________________________________________________________________ Added: svn:executable + * Added: svn:mime-type + application/octet-stream Added: trunk/dsim/test/boost/spirit/action_parser.cpp =================================================================== --- trunk/dsim/test/boost/spirit/action_parser.cpp (rev 0) +++ trunk/dsim/test/boost/spirit/action_parser.cpp 2010-11-10 16:56:23 UTC (rev 148) @@ -0,0 +1,104 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +#include <boost/config/warning_disable.hpp> +#include <boost/spirit/include/qi.hpp> +#include <boost/lambda/lambda.hpp> +#include <boost/bind.hpp> + +#include <iostream> + +// Presented are various ways to attach semantic actions +// * Using plain function pointer +// * Using simple function object +// * Using boost.bind with a plain function +// * Using boost.bind with a member function +// * Using boost.lambda + +//[tutorial_semantic_action_functions +namespace client +{ + namespace qi = boost::spirit::qi; + + // A plain function + void print(int const& i) + { + std::cout << i << std::endl; + } + + // A member function + struct writer + { + void print(int const& i) const + { + std::cout << i << std::endl; + } + }; + + // A function object + struct print_action + { + void operator()(int const& i, qi::unused_type, qi::unused_type) const + { + std::cout << i << std::endl; + } + }; +} +//] + +int main() +{ + using boost::spirit::qi::int_; + using boost::spirit::qi::parse; + using client::print; + using client::writer; + using client::print_action; + + { // example using plain function + + char const *first = "{42}", *last = first + std::strlen(first); + //[tutorial_attach_actions1 + parse(first, last, '{' >> int_[&print] >> '}'); + //] + } + + { // example using simple function object + + char const *first = "{43}", *last = first + std::strlen(first); + //[tutorial_attach_actions2 + parse(first, last, '{' >> int_[print_action()] >> '}'); + //] + } + + { // example using boost.bind with a plain function + + char const *first = "{44}", *last = first + std::strlen(first); + //[tutorial_attach_actions3 + parse(first, last, '{' >> int_[boost::bind(&print, _1)] >> '}'); + //] + } + + { // example using boost.bind with a member function + + char const *first = "{44}", *last = first + std::strlen(first); + //[tutorial_attach_actions4 + writer w; + parse(first, last, '{' >> int_[boost::bind(&writer::print, &w, _1)] >> '}'); + //] + } + + { // example using boost.lambda + + namespace lambda = boost::lambda; + char const *first = "{45}", *last = first + std::strlen(first); + using lambda::_1; + //[tutorial_attach_actions5 + parse(first, last, '{' >> int_[std::cout << _1 << '\n'] >> '}'); + //] + } + + return 0; +} Added: trunk/dsim/test/boost/spirit/bad_input.csv =================================================================== --- trunk/dsim/test/boost/spirit/bad_input.csv (rev 0) +++ trunk/dsim/test/boost/spirit/bad_input.csv 2010-11-10 16:56:23 UTC (rev 148) @@ -0,0 +1,5 @@ +# test +# +# bad input + +123;42.0;a;1.4 Added: trunk/dsim/test/boost/spirit/complex_parser =================================================================== (Binary files differ) Property changes on: trunk/dsim/test/boost/spirit/complex_parser ___________________________________________________________________ Added: svn:executable + * Added: svn:mime-type + application/octet-stream Added: trunk/dsim/test/boost/spirit/complex_parser.cpp =================================================================== --- trunk/dsim/test/boost/spirit/complex_parser.cpp (rev 0) +++ trunk/dsim/test/boost/spirit/complex_parser.cpp 2010-11-10 16:56:23 UTC (rev 148) @@ -0,0 +1,101 @@ +/*============================================================================= + Copyright (c) 2002-2010 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A complex number micro parser. +// +// [ JDG May 10, 2002 ] spirit1 +// [ JDG May 9, 2007 ] spirit2 +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/config/warning_disable.hpp> +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> + +#include <iostream> +#include <string> +#include <complex> + +/////////////////////////////////////////////////////////////////////////////// +// Our complex number parser/compiler +/////////////////////////////////////////////////////////////////////////////// +//[tutorial_complex_number +namespace client +{ + template <typename Iterator> + bool parse_complex(Iterator first, Iterator last, std::complex<double>& c) + { + using boost::spirit::qi::double_; + using boost::spirit::qi::_1; + using boost::spirit::qi::phrase_parse; + using boost::spirit::ascii::space; + using boost::phoenix::ref; + + double rN = 0.0; + double iN = 0.0; + bool r = phrase_parse(first, last, + + // Begin grammar + ( + '(' >> double_[ref(rN) = _1] + >> -(',' >> double_[ref(iN) = _1]) >> ')' + | double_[ref(rN) = _1] + ), + // End grammar + + space); + + if (!r || first != last) // fail if we did not get a full match + return false; + c = std::complex<double>(rN, iN); + return r; + } +} +//] + +//////////////////////////////////////////////////////////////////////////// +// Main program +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "\t\tA complex number micro parser for Spirit...\n\n"; + std::cout << "/////////////////////////////////////////////////////////\n\n"; + + std::cout << "Give me a complex number of the form r or (r) or (r,i) \n"; + std::cout << "Type [q or Q] to quit\n\n"; + + std::string str; + while (getline(std::cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + std::complex<double> c; + if (client::parse_complex(str.begin(), str.end(), c)) + { + std::cout << "-------------------------\n"; + std::cout << "Parsing succeeded\n"; + std::cout << "got: " << c << std::endl; + std::cout << "\n-------------------------\n"; + } + else + { + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "-------------------------\n"; + } + } + + std::cout << "Bye... :-) \n\n"; + return 0; +} + + Added: trunk/dsim/test/boost/spirit/employee_parser =================================================================== (Binary files differ) Property changes on: trunk/dsim/test/boost/spirit/employee_parser ___________________________________________________________________ Added: svn:executable + * Added: svn:mime-type + application/octet-stream Added: trunk/dsim/test/boost/spirit/employee_parser.cpp =================================================================== --- trunk/dsim/test/boost/spirit/employee_parser.cpp (rev 0) +++ trunk/dsim/test/boost/spirit/employee_parser.cpp 2010-11-10 16:56:23 UTC (rev 148) @@ -0,0 +1,152 @@ + +/*============================================================================= + Copyright (c) 2002-2010 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A parser for arbitrary tuples. This example presents a parser +// for an employee structure. +// +// [ JDG May 9, 2007 ] +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/config/warning_disable.hpp> +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/phoenix_object.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/fusion/include/io.hpp> + +#include <iostream> +#include <string> +#include <complex> + +namespace client +{ + namespace qi = boost::spirit::qi; + namespace ascii = boost::spirit::ascii; + + /////////////////////////////////////////////////////////////////////////// + // Our employee struct + /////////////////////////////////////////////////////////////////////////// + //[tutorial_employee_struct + struct employee + { + int age; + std::string surname; + std::string forename; + double salary; + }; + //] +} + +// We need to tell fusion about our employee struct +// to make it a first-class fusion citizen. This has to +// be in global scope. + +//[tutorial_employee_adapt_struct +BOOST_FUSION_ADAPT_STRUCT( + client::employee, + (int, age) + (std::string, surname) + (std::string, forename) + (double, salary) +) +//] + +namespace client +{ + /////////////////////////////////////////////////////////////////////////////// + // Our employee parser + /////////////////////////////////////////////////////////////////////////////// + //[tutorial_employee_parser + template <typename Iterator> + struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type> + { + employee_parser() : employee_parser::base_type(start) + { + using qi::int_; + using qi::lit; + using qi::double_; + using qi::lexeme; + using ascii::char_; + + quoted_string %= lexeme['"' >> +(char_ - '"') >> '"']; + + start %= + lit("employee") + >> '{' + >> int_ >> ',' + >> quoted_string >> ',' + >> quoted_string >> ',' + >> double_ + >> '}' + ; + } + + qi::rule<Iterator, std::string(), ascii::space_type> quoted_string; + qi::rule<Iterator, employee(), ascii::space_type> start; + }; + //] +} + +//////////////////////////////////////////////////////////////////////////// +// Main program +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "\t\tAn employee parser for Spirit...\n\n"; + std::cout << "/////////////////////////////////////////////////////////\n\n"; + + std::cout + << "Give me an employee of the form :" + << "employee{age, \"surname\", \"forename\", salary } \n"; + std::cout << "Type [q or Q] to quit\n\n"; + + using boost::spirit::ascii::space; + typedef std::string::const_iterator iterator_type; + typedef client::employee_parser<iterator_type> employee_parser; + + employee_parser g; // Our grammar + std::string str; + while (getline(std::cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + client::employee emp; + std::string::const_iterator iter = str.begin(); + std::string::const_iterator end = str.end(); + bool r = phrase_parse(iter, end, g, space, emp); + + if (r && iter == end) + { + std::cout << boost::fusion::tuple_open('['); + std::cout << boost::fusion::tuple_close(']'); + std::cout << boost::fusion::tuple_delimiter(", "); + + std::cout << "-------------------------\n"; + std::cout << "Parsing succeeded\n"; + std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl; + std::cout << "\n-------------------------\n"; + } + else + { + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "-------------------------\n"; + } + } + + std::cout << "Bye... :-) \n\n"; + return 0; +} + + Added: trunk/dsim/test/boost/spirit/good_input.csv =================================================================== --- trunk/dsim/test/boost/spirit/good_input.csv (rev 0) +++ trunk/dsim/test/boost/spirit/good_input.csv 2010-11-10 16:56:23 UTC (rev 148) @@ -0,0 +1,5 @@ +# test +# +# good input +8 ; +6; 7; Added: trunk/dsim/test/boost/spirit/num_list1_parser =================================================================== (Binary files differ) Property changes on: trunk/dsim/test/boost/spirit/num_list1_parser ___________________________________________________________________ Added: svn:executable + * Added: svn:mime-type + application/octet-stream Added: trunk/dsim/test/boost/spirit/num_list1_parser.cpp =================================================================== --- trunk/dsim/test/boost/spirit/num_list1_parser.cpp (rev 0) +++ trunk/dsim/test/boost/spirit/num_list1_parser.cpp 2010-11-10 16:56:23 UTC (rev 148) @@ -0,0 +1,90 @@ +/*============================================================================= + Copyright (c) 2002-2010 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// This sample demontrates a parser for a comma separated list of numbers. +// No actions. +// +// [ JDG May 10, 2002 ] spirit1 +// [ JDG March 24, 2007 ] spirit2 +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/config/warning_disable.hpp> +#include <boost/spirit/include/qi.hpp> + +#include <iostream> +#include <string> +#include <vector> + +namespace client +{ + namespace qi = boost::spirit::qi; + namespace ascii = boost::spirit::ascii; + + /////////////////////////////////////////////////////////////////////////// + // Our number list parser + /////////////////////////////////////////////////////////////////////////// + //[tutorial_numlist1 + template <typename Iterator> + bool parse_numbers(Iterator first, Iterator last) + { + using qi::double_; + using qi::phrase_parse; + using ascii::space; + + bool r = phrase_parse( + first, /*< start iterator >*/ + last, /*< end iterator >*/ + double_ >> *(',' >> double_), /*< the parser >*/ + space /*< the skip-parser >*/ + ); + if (first != last) // fail if we did not get a full match + return false; + return r; + } + //] +} + +//////////////////////////////////////////////////////////////////////////// +// Main program +//////////////////////////////////////////////////////////////////////////// +int +main() +{ + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "\t\tA comma separated list parser for Spirit...\n\n"; + std::cout << "/////////////////////////////////////////////////////////\n\n"; + + std::cout << "Give me a comma separated list of numbers.\n"; + std::cout << "Type [q or Q] to quit\n\n"; + + std::string str; + while (getline(std::cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + if (client::parse_numbers(str.begin(), str.end())) + { + std::cout << "-------------------------\n"; + std::cout << "Parsing succeeded\n"; + std::cout << str << " Parses OK: " << std::endl; + } + else + { + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "-------------------------\n"; + } + } + + std::cout << "Bye... :-) \n\n"; + return 0; +} + + Added: trunk/dsim/test/boost/spirit/roman_parser =================================================================== (Binary files differ) Property changes on: trunk/dsim/test/boost/spirit/roman_parser ___________________________________________________________________ Added: svn:executable + * Added: svn:mime-type + application/octet-stream Added: trunk/dsim/test/boost/spirit/roman_parser.cpp =================================================================== --- trunk/dsim/test/boost/spirit/roman_parser.cpp (rev 0) +++ trunk/dsim/test/boost/spirit/roman_parser.cpp 2010-11-10 16:56:23 UTC (rev 148) @@ -0,0 +1,186 @@ +/*============================================================================= + Copyright (c) 2001-2010 Joel de Guzman + + Distributed under the Boost Software License, Version 1.0. (See accompanying + file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ +/////////////////////////////////////////////////////////////////////////////// +// +// A Roman Numerals Parser (demonstrating the symbol table). This is +// discussed in the "Symbols" chapter in the Spirit User's Guide. +// +// [ JDG August 22, 2002 ] spirit1 +// [ JDG March 13, 2007 ] spirit2 +// +/////////////////////////////////////////////////////////////////////////////// + +#include <boost/config/warning_disable.hpp> +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> + +#include <iostream> +#include <string> + +namespace client +{ + namespace qi = boost::spirit::qi; + namespace ascii = boost::spirit::ascii; + + /////////////////////////////////////////////////////////////////////////////// + // Parse roman hundreds (100..900) numerals using the symbol table. + // Notice that the data associated with each slot is the parser's attribute + // (which is passed to attached semantic actions). + /////////////////////////////////////////////////////////////////////////////// + //[tutorial_roman_hundreds + struct hundreds_ : qi::symbols<char, unsigned> + { + hundreds_() + { + add + ("C" , 100) + ("CC" , 200) + ("CCC" , 300) + ("CD" , 400) + ("D" , 500) + ("DC" , 600) + ("DCC" , 700) + ("DCCC" , 800) + ("CM" , 900) + ; + } + + } hundreds; + //] + + /////////////////////////////////////////////////////////////////////////////// + // Parse roman tens (10..90) numerals using the symbol table. + /////////////////////////////////////////////////////////////////////////////// + //[tutorial_roman_tens + struct tens_ : qi::symbols<char, unsigned> + { + tens_() + { + add + ("X" , 10) + ("XX" , 20) + ("XXX" , 30) + ("XL" , 40) + ("L" , 50) + ("LX" , 60) + ("LXX" , 70) + ("LXXX" , 80) + ("XC" , 90) + ; + } + + } tens; + //] + + /////////////////////////////////////////////////////////////////////////////// + // Parse roman ones (1..9) numerals using the symbol table. + /////////////////////////////////////////////////////////////////////////////// + //[tutorial_roman_ones + struct ones_ : qi::symbols<char, unsigned> + { + ones_() + { + add + ("I" , 1) + ("II" , 2) + ("III" , 3) + ("IV" , 4) + ("V" , 5) + ("VI" , 6) + ("VII" , 7) + ("VIII" , 8) + ("IX" , 9) + ; + } + + } ones; + //] + + /////////////////////////////////////////////////////////////////////////////// + // roman (numerals) grammar + // + // Note the use of the || operator. The expression + // a || b reads match a or b and in sequence. Try + // defining the roman numerals grammar in YACC or + // PCCTS. Spirit rules! :-) + /////////////////////////////////////////////////////////////////////////////// + //[tutorial_roman_grammar + template <typename Iterator> + struct roman : qi::grammar<Iterator, unsigned()> + { + roman() : roman::base_type(start) + { + using qi::eps; + using qi::lit; + using qi::_val; + using qi::_1; + using ascii::char_; + + start = eps [_val = 0] >> + ( + +lit('M') [_val += 1000] + || hundreds [_val += _1] + || tens [_val += _1] + || ones [_val += _1] + ) + ; + } + + qi::rule<Iterator, unsigned()> start; + }; + //] +} + +/////////////////////////////////////////////////////////////////////////////// +// Main program +/////////////////////////////////////////////////////////////////////////////// +int +main() +{ + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "\t\tRoman Numerals Parser\n\n"; + std::cout << "/////////////////////////////////////////////////////////\n\n"; + std::cout << "Type a Roman Numeral ...or [q or Q] to quit\n\n"; + + typedef std::string::const_iterator iterator_type; + typedef client::roman<iterator_type> roman; + + roman roman_parser; // Our grammar + + std::string str; + unsigned result; + while (std::getline(std::cin, str)) + { + if (str.empty() || str[0] == 'q' || str[0] == 'Q') + break; + + std::string::const_iterator iter = str.begin(); + std::string::const_iterator end = str.end(); + //[tutorial_roman_grammar_parse + bool r = parse(iter, end, roman_parser, result); + + if (r && iter == end) + { + std::cout << "-------------------------\n"; + std::cout << "Parsing succeeded\n"; + std::cout << "result = " << result << std::endl; + std::cout << "-------------------------\n"; + } + else + { + std::string rest(iter, end); + std::cout << "-------------------------\n"; + std::cout << "Parsing failed\n"; + std::cout << "stopped at: \": " << rest << "\"\n"; + std::cout << "-------------------------\n"; + } + //] + } + + std::cout << "Bye... :-) \n\n"; + return 0; +} Modified: trunk/dsim/test/boost/spirit/schedule_parser.cpp =================================================================== --- trunk/dsim/test/boost/spirit/schedule_parser.cpp 2010-11-02 17:47:57 UTC (rev 147) +++ trunk/dsim/test/boost/spirit/schedule_parser.cpp 2010-11-10 16:56:23 UTC (rev 148) @@ -1,130 +1,25 @@ // STL -#include <cassert> -#include <iostream> +#include <istream> #include <sstream> +#include <iostream> #include <fstream> -#include <string> -#include <map> #include <set> #include <vector> // Boost (Extended STL) #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/gregorian/gregorian.hpp> // Boost Spirit (Parsing) -//#define BOOST_SPIRIT_DEBUG -#include <boost/spirit/home/classic/core.hpp> -#include <boost/spirit/home/classic/attribute.hpp> -#include <boost/spirit/home/classic/utility/functor_parser.hpp> -#include <boost/spirit/home/classic/utility/loops.hpp> -#include <boost/spirit/home/classic/utility/chset.hpp> -#include <boost/spirit/home/classic/utility/confix.hpp> -#include <boost/spirit/home/classic/iterator/file_iterator.hpp> -#include <boost/spirit/home/classic/actor/push_back_actor.hpp> -#include <boost/spirit/home/classic/actor/assign_actor.hpp> +#include <boost/spirit/include/qi.hpp> +#include <boost/spirit/include/phoenix_core.hpp> +#include <boost/spirit/include/phoenix_operator.hpp> +#include <boost/spirit/include/phoenix_object.hpp> +#include <boost/fusion/include/adapt_struct.hpp> +#include <boost/spirit/include/support_multi_pass.hpp> +#include <boost/fusion/include/io.hpp> +#include <boost/lambda/lambda.hpp> -// Type definitions -typedef char char_t; -//typedef char const* iterator_t; -typedef boost::spirit::classic::file_iterator<char_t> iterator_t; -typedef boost::spirit::classic::scanner<iterator_t> scanner_t; -typedef boost::spirit::classic::rule<scanner_t> rule_t; -/** LegCabin-Details. */ -struct Cabin_T { - // Attributes - std::string _cabinCode; - double _capacity; - - void display() const { - std::cout << " " << _cabinCode << " " << _capacity << ", "; - } -}; - -/** List of Cabin-Detail strucutres. */ -typedef std::vector<Cabin_T> CabinList_T; - -/** Leg. */ -struct Leg_T { - // Attributes - std::string _boardPoint; - boost::posix_time::time_duration _boardTime; - boost::gregorian::date_duration _boardDateOffSet; - std::string _offPoint; - boost::posix_time::time_duration _offTime; - boost::gregorian::date_duration _offDateOffSet; - boost::posix_time::time_duration _elapsed; - CabinList_T _cabinList; - - /** Constructor. */ - Leg_T () : _boardDateOffSet (0), _offDateOffSet (0) {} - - void display() const { - std::cout << " " << _boardPoint << " / " - << boost::posix_time::to_simple_string (_boardTime) - << " -- " << _offPoint << " / " - << boost::posix_time::to_simple_string (_offTime) - << " --> " << boost::posix_time::to_simple_string (_elapsed) - << std::endl; - for (CabinList_T::const_iterator itCabin = _cabinList.begin(); - itCabin != _cabinList.end(); itCabin++) { - const Cabin_T& lCabin = *itCabin; - lCabin.display(); - } - std::cout << std::endl; - } -}; - -/** List of Leg strucutres. */ -typedef std::vector<Leg_T> LegList_T; - -/** SegmentCabin-Details. */ -struct SegmentCabin_T { - // Attributes - std::string _cabinCode; - std::string _classes; - - void display() const { - std::cout << " " << _cabinCode << " " << _classes << ", "; - } -}; - -/** List of SegmentCabin-Detail strucutres. */ -typedef std::vector<SegmentCabin_T> SegmentCabinList_T; - -/** Segment. */ -struct Segment_T { - // Attributes - std::string _boardPoint; - boost::posix_time::time_duration _boardTime; - boost::gregorian::date_duration _boardDateOffSet; - std::string _offPoint; - boost::posix_time::time_duration _offTime; - boost::gregorian::date_duration _offDateOffSet; - boost::posix_time::time_duration _elapsed; - SegmentCabinList_T _cabinList; - - /** Constructor. */ - Segment_T () : _boardDateOffSet (0), _offDateOffSet (0) {} - - void display() const { - std::cout << " " << _boardPoint << " / " - << boost::posix_time::to_simple_string (_boardTime) - << " -- " << _offPoint << " / " - << boost::posix_time::to_simple_string (_offTime) - << " --> " << boost::posix_time::to_simple_string (_elapsed) - << std::endl; - for (SegmentCabinList_T::const_iterator itCabin = _cabinList.begin(); - itCabin != _cabinList.end(); itCabin++) { - const SegmentCabin_T& lCabin = *itCabin; - lCabin.display(); - } - std::cout << std::endl; - } -}; - -/** List of Segment strucutres. */ -typedef std::vector<Segment_T> SegmentList_T; - +typedef std::string::const_iterator iterator_t; /** Flight-Period. */ struct FlightPeriod_T { // Attributes @@ -133,778 +28,225 @@ boost::gregorian::date _dateRangeStart; boost::gregorian::date _dateRangeEnd; std::string _dow; - LegList_T _legList; - SegmentList_T _segmentList; - - /** Constructor. */ - FlightPeriod_T () : _legAlreadyDefined (false), _itSeconds (0) {} + std::string _cabinCode; +}; - /** Set the date from the staging details. */ - boost::gregorian::date getDate() const { - return boost::gregorian::date (_itYear, _itMonth, _itDay); +/** Store the parsed airline code. */ +template <typename FLIGHT_PERIOD> +struct store_airline_code { + store_airline_code (FLIGHT_PERIOD& ioFlightPeriod) + : _flightPeriod (ioFlightPeriod) {} + + void operator() (iterator_t iStr, iterator_t iStrEnd) const { + std::string lAirlineCode (iStr, iStrEnd); + _flightPeriod._airlineCode = lAirlineCode; + // std::cout << "Airline code: " << lAirlineCode << std::endl; } - - /** Set the time from the staging details. */ - boost::posix_time::time_duration getTime() const { - return boost::posix_time::hours (_itHours) - + boost::posix_time::minutes (_itMinutes) - + boost::posix_time::seconds (_itSeconds); - } - - void display() const { - std::cout << _airlineCode << _flightNumber - << ", " << boost::gregorian::to_simple_string (_dateRangeStart) - << " - " << boost::gregorian::to_simple_string (_dateRangeEnd) - << " - " << _dow - << std::endl; - for (LegList_T::const_iterator itLeg = _legList.begin(); - itLeg != _legList.end(); itLeg++) { - const Leg_T& lLeg = *itLeg; - lLeg.display(); - } + FLIGHT_PERIOD& _flightPeriod; +}; - for (SegmentList_T::const_iterator itSegment = _segmentList.begin(); - itSegment != _segmentList.end(); itSegment++) { - const Segment_T& lSegment = *itSegment; - lSegment.display(); - } +/** Store the parsed cabin code. */ +template <typename FLIGHT_PERIOD> +struct store_cabin_code { + store_cabin_code (FLIGHT_PERIOD& ioFlightPeriod) + : _flightPeriod (ioFlightPeriod) {} - //std::cout << "[Debug] - Staging Leg: "; - //_itLeg.display(); - //std::cout << "[Debug] - Staging Cabin: "; - //_itCabin.display(); - //std::cout << "[Debug] - Staging Segment: "; - //_itSegment.display(); + void operator() (char iChar) const { + _flightPeriod._cabinCode = iChar; + // std::cout << "Cabin code: " << lCabinCode << std::endl; } - - /** Add the given airport to the internal lists (if not already existing). */ - void addAirport (const std::string& iAirport) { - std::set<std::string>::const_iterator itAirport = - _airportList.find (iAirport); - if (itAirport == _airportList.end()) { - // Add the airport code to the airport set - const bool insertSuccessful = _airportList.insert (iAirport).second; - - if (insertSuccessful == false) { - // TODO: throw an exception - } - // Add the airport code to the airport vector - _airportOrderedList.push_back (iAirport); - } - } - - /** Build the routing (segments). */ - void buildSegments () { - // The list of airports encompasses all the airports on which - // the flight takes off or lands. Moreover, that list is - // time-ordered: the first airport is the initial departure of - // the flight, and the last airport is the eventual point of - // rest of the flight. - // Be l the size of the ordered list of airports. - // We want to generate all the segment combinations from the legs - // and, hence, from all the possible (time-ordered) airport pairs. - // Thus, we both iterator on i=0...l-1 and j=i+1...l - assert (_airportOrderedList.size() >= 2); - - _segmentList.clear(); - for (std::vector<std::string>::const_iterator itAirport_i = - _airportOrderedList.begin(); - itAirport_i != _airportOrderedList.end()-1; ++itAirport_i) { - for (std::vector<std::string>::const_iterator itAirport_j = - itAirport_i + 1; - itAirport_j != _airportOrderedList.end(); ++itAirport_j) { - Segment_T lSegment; - lSegment._boardPoint = *itAirport_i; - lSegment._offPoint = *itAirport_j; - - _segmentList.push_back (lSegment); - } - } - - // Clear the lists of airports, so that it is ready for the next flight - _airportList.clear(); - _airportOrderedList.clear(); - } - - /** Add, to the Segment whose key corresponds to the - given (board point, off point) pair, the specific segment cabin - details (mainly, the list of the class codes). - <br>Note that the Segment structure is retrieved from the internal - list, already filled by a previous step (the buildSegments() - method). */ - void addSegmentCabin (const Segment_T& iSegment, - const SegmentCabin_T& iCabin) { - // Retrieve the Segment structure corresponding to the (board, off) point - // pair. - SegmentList_T::iterator itSegment = _segmentList.begin(); - for ( ; itSegment != _segmentList.end(); ++itSegment) { - const Segment_T& lSegment = *itSegment; - - const std::string& lBoardPoint = iSegment._boardPoint; - const std::string& lOffPoint = iSegment._offPoint; - if (lSegment._boardPoint == lBoardPoint - && lSegment._offPoint == lOffPoint) { - break; - } - } - // If the segment key (airport pair) given in the schedule input file - // does not correspond to the leg (board, off) points, throw an exception - // so that the user knows the schedule input file is corrupted. - if (itSegment == _segmentList.end()) { - std::cerr << "Within the schedule input file, there is a flight for which the airports of segments and those of the legs do not correspond."; - throw std::exception(); - } - - // Add the Cabin structure to the Segment Cabin structure. - assert (itSegment != _segmentList.end()); - Segment_T& lSegment = *itSegment; - lSegment._cabinList.push_back (iCabin); - } - - /** Add, to all the Segment, the general segment cabin details - (mainly, the list of the class codes). - <br>Note that the Segment structures are stored within the internal - list, already filled by a previous step (the buildSegments() - method). */ - void addSegmentCabin (const SegmentCabin_T& iCabin) { - // Iterate on all the Segment (as they get the same cabin definitions) - for (SegmentList_T::iterator itSegment = _segmentList.begin(); - itSegment != _segmentList.end(); ++itSegment) { - Segment_T& lSegment = *itSegment; - lSegment._cabinList.push_back (iCabin); - } - } - - /** Staging Leg (resp. Cabin) structure, gathering the result of the iteration - on one leg (resp. cabin). */ - bool _legAlreadyDefined; - Leg_T _itLeg; - Cabin_T _itCabin; - - /** Staging Date. */ - unsigned int _itYear; - unsigned int _itMonth; - unsigned int _itDay; - - /** Staging Time. */ - long _itHours; - long _itMinutes; - long _itSeconds; - int _dateOffSet; - - /** Staging Airport List (helper to derive the list of Segment - structures). */ - std::set<std::string> _airportList; - std::vector<std::string> _airportOrderedList; - - /** Staging Segment-related attributes. */ - bool _areSegmentDefinitionsSpecific; - Segment_T _itSegment; - SegmentCabin_T _itSegmentCabin; + FLIGHT_PERIOD& _flightPeriod; }; - -/////////////////////////////////////////////////////////////////////////////// -// -// Semantic actions -// -/////////////////////////////////////////////////////////////////////////////// -namespace { - /** Store the parsed airline code. */ - struct store_airline_code { - store_airline_code (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - std::string lAirlineCode (iStr, iStrEnd); - _flightPeriod._airlineCode = lAirlineCode; - // std::cout << "Airline code: " << lAirlineCode << std::endl; - // As that's the beginning of a new flight, the list of legs must be reset - _flightPeriod._legList.clear(); - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the parsed flight number. */ - struct store_flight_number { - store_flight_number (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} +// /////////// Utilities ///////////// - void operator() (unsigned int iNumber) const { - _flightPeriod._flightNumber = iNumber; - // std::cout << "Flight number: " << iNumber << std::endl; - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the start of the date range. */ - struct store_date_range_start { - store_date_range_start (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - _flightPeriod._dateRangeStart = _flightPeriod.getDate(); - // std::cout << "Date Range Start: " - // << _flightPeriod._dateRangeStart << std::endl; - - // Reset the number of seconds - _flightPeriod._itSeconds = 0; - } - - FlightPeriod_T& _flightPeriod; - }; +/** 1-digit-integer parser */ +boost::spirit::qi::uint_parser<int, 10, 1, 1> int1_p; - /** Store the end of the date range. */ - struct store_date_range_end { - store_date_range_end (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - _flightPeriod._dateRangeEnd = _flightPeriod.getDate(); - // std::cout << "Date Range End: " - // << _flightPeriod._dateRangeEnd << std::endl; - - // Reset the number of seconds - _flightPeriod._itSeconds = 0; - } - - FlightPeriod_T& _flightPeriod; - }; +/** 2-digit-integer parser */ +boost::spirit::qi::uint_parser<int, 10, 2, 2> uint2_p; - /** Store the DOW (day of the Week). */ - struct store_dow { - store_dow (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} +/** 4-digit-integer parser */ +boost::spirit::qi::uint_parser<int, 10, 4, 4> uint4_p; - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - std::string lDow (iStr, iStrEnd); - _flightPeriod._dow = lDow; - // std::cout << "DOW: " << lDow << std::endl; - } - - FlightPeriod_T& _flightPeriod; - }; +/** Up-to-4-digit-integer parser */ +boost::spirit::qi::uint_parser<int, 10, 1, 4> uint1_4_p; - /** Store the parsed board point. */ - struct store_board_point { - store_board_point (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - std::string lBoardPoint (iStr, iStrEnd); - // std::cout << "Board point: " << lBoardPoint << std::endl; - - // If a leg has already been parsed, add it to the FlightPeriod - if (_flightPeriod._legAlreadyDefined == true) { - _flightPeriod._legList.push_back (_flightPeriod._itLeg); - } else { - _flightPeriod._legAlreadyDefined = true; - } - - // Set the (new) board point - _flightPeriod._itLeg._boardPoint = lBoardPoint; - - // As that's the beginning of a new leg, the list of cabins must be reset - _flightPeriod._itLeg._cabinList.clear(); - - // Add the airport code if it is not already stored in the airport lists - _flightPeriod.addAirport (lBoardPoint); - } - - FlightPeriod_T& _flightPeriod; - }; - /** Store the parsed off point. */ - struct store_off_point { - store_off_point (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} +//////////////////////////////////////////////////////////////////////////// +// Parser +//////////////////////////////////////////////////////////////////////////// +template <typename ITERATOR, typename FLIGHT_PERIOD> +struct FlightPeriodParser : + boost::spirit::qi::grammar<ITERATOR, boost::spirit::ascii::space_type > { - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - std::string lOffPoint (iStr, iStrEnd); - _flightPeriod._itLeg._offPoint = lOffPoint; - // std::cout << "Off point: " << lOffPoint << std::endl; - - // Add the airport code if it is not already stored in the airport lists - _flightPeriod.addAirport (lOffPoint); - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the board time. */ - struct store_board_time { - store_board_time (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - _flightPeriod._itLeg._boardTime = _flightPeriod.getTime(); - - // Reset the number of seconds - _flightPeriod._itSeconds = 0; - - // Reset the date off-set - _flightPeriod._dateOffSet = 0; - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the off time. */ - struct store_off_time { - store_off_time (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - _flightPeriod._itLeg._offTime = _flightPeriod.getTime(); - - // Reset the number of seconds - _flightPeriod._itSeconds = 0; - - // As the board date off set is optional, it can be set only afterwards, - // based on the staging date off-set value (_flightPeriod._dateOffSet). - const boost::gregorian::date_duration lDateOffSet (_flightPeriod._dateOffSet); - _flightPeriod._itLeg._boardDateOffSet = lDateOffSet; - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the elapsed time. */ - struct store_elapsed_time { - store_elapsed_time (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - _flightPeriod._itLeg._elapsed = _flightPeriod.getTime(); - - // Reset the number of seconds - _flightPeriod._itSeconds = 0; - - // As the board date off set is optional, it can be set only afterwards, - // based on the staging date off-set value (_flightPeriod._dateOffSet). - const boost::gregorian::date_duration lDateOffSet (_flightPeriod._dateOffSet); - _flightPeriod._itLeg._offDateOffSet = lDateOffSet; - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the parsed cabin code. */ - struct store_cabin_code { - store_cabin_code (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - void operator() (char iChar) const { - _flightPeriod._itCabin._cabinCode = iChar; - // std::cout << "Cabin code: " << iChar << std::endl; - } - - FlightPeriod_T& _flightPeriod; - }; + typedef store_airline_code<FLIGHT_PERIOD> store_airline_code_t; + typedef store_cabin_code<FLIGHT_PERIOD> store_cabin_code_t; - /** Store the parsed capacity. */ - struct store_capacity { - store_capacity (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} + FLIGHT_PERIOD _t; - void operator() (double iReal) const { - _flightPeriod._itCabin._capacity = iReal; - // std::cout << "Capacity: " << iReal << std::endl; + FlightPeriodParser () : + FlightPeriodParser::base_type(start) { - // The capacity is the last (according to arrival order) detail - // of the cabin. Hence, when a capacity is parsed, it means that - // the full cabin details have already been parsed as well: the - // cabin can thus be added to the leg. - _flightPeriod._itLeg._cabinList.push_back (_flightPeriod._itCabin); - } + using boost::spirit::ascii::string; + using boost::spirit::ascii::char_; + using boost::spirit::qi::lexeme; + using boost::spirit::qi::repeat; + using boost::spirit::qi::double_; + using boost::lambda::_1; - FlightPeriod_T& _flightPeriod; - }; - - /** Store whether or not all the segments are the same. */ - struct store_segment_specificity { - store_segment_specificity (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) { - } - void operator() (char iChar) const { - if (iChar == '0') { - _flightPeriod._areSegmentDefinitionsSpecific = false; - } else { - _flightPeriod._areSegmentDefinitionsSpecific = true; - } + start = (comment | flight_period) ; - // Do a few sanity checks: the two lists should get exactly the same - // content (in terms of airport codes). The only difference is that one - // is a STL set, and the other a STL vector. - assert (_flightPeriod._airportList.size() - == _flightPeriod._airportOrderedList.size()); - assert (_flightPeriod._airportList.size() >= 2); - - // Since all the legs have now been parsed, we get all the airports - // and the segments may be built. - _flightPeriod.buildSegments(); - } + comment = lexeme[ (repeat(2)[char_("/")]) ] >> *(char_); - FlightPeriod_T& _flightPeriod; - }; + flight_period = airline_code + >> ';' >> flight_number + >> ';' >> date + >> ';' >> date + >> ';' >> dow + >> ';' + >> leg_list + >> segment_list + ; - /** Store the board point of the segment. */ - struct store_segment_board_point { - store_segment_board_point (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) { - } - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - std::string lBoardPoint (iStr, iStrEnd); - _flightPeriod._itSegment._boardPoint = lBoardPoint; - // std::cout << "Board point: " << lBoardPoint << std::endl; - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the off point of the segment. */ - struct store_segment_off_point { - store_segment_off_point (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) { - } - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - std::string lOffPoint (iStr, iStrEnd); - _flightPeriod._itSegment._offPoint = lOffPoint; - // std::cout << "Off point: " << lOffPoint << std::endl; - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the off point of the segment. */ - struct store_segment_cabin_code { - store_segment_cabin_code (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) { - } + airline_code = lexeme[ (repeat(2)[char_("A-Z")]) ]; - void operator() (char iChar) const { - _flightPeriod._itSegmentCabin._cabinCode = iChar; - // std::cout << "Cabin code: " << iChar << std::endl; - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Store the classes of the segment-cabin. */ - struct store_classes { - store_classes (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) { - } - - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - std::string lClasses (iStr, iStrEnd); - _flightPeriod._itSegmentCabin._classes = lClasses; - // std::cout << "Classes: " << lClasses << std::endl; - - // The list of classes is the last (according to the arrival order - // within the schedule input file) detail of the segment cabin. Hence, - // when a list of classes is parsed, it means that the full segment - // cabin details have already been parsed as well: the segment cabin - // can thus be added to the segment. - if (_flightPeriod._areSegmentDefinitionsSpecific == true) { - _flightPeriod.addSegmentCabin (_flightPeriod._itSegment, - _flightPeriod._itSegmentCabin); - } else { - _flightPeriod.addSegmentCabin (_flightPeriod._itSegmentCabin); - } - } - - FlightPeriod_T& _flightPeriod; - }; - - /** Mark the end of the flight-period parsing. */ - struct do_end_flight { - do_end_flight (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) {} - - // void operator() (char iChar) const { - void operator() (iterator_t iStr, iterator_t iStrEnd) const { - // std::cout << "End of Flight-Period " << std::endl; - - assert (_flightPeriod._legAlreadyDefined == true); - _flightPeriod._legList.push_back (_flightPeriod._itLeg); - // The lists of legs and cabins must be reset - _flightPeriod._legAlreadyDefined = false; - _flightPeriod._itLeg._cabinList.clear(); - - // Display the result - _flightPeriod.display(); - } - - FlightPeriod_T& _flightPeriod; - }; -} - -// /////////// Utilities ///////////// -/** 1-digit-integer parser */ -boost::spirit::classic::int_parser<unsigned int, 10, 1, 1> int1_p; -/** 2-digit-integer parser */ -boost::spirit::classic::uint_parser<int, 10, 2, 2> uint2_p; -/** 4-digit-integer parser */ -boost::spirit::classic::uint_parser<int, 10, 4, 4> uint4_p; -/** Up-to-4-digit-integer parser */ -boost::spirit::classic::uint_parser<int, 10, 1, 4> uint1_4_p; - -/////////////////////////////////////////////////////////////////////////////// -// -// Our calculator grammar (using subrules) -// -/////////////////////////////////////////////////////////////////////////////// - /** - AirlineCode; FlightNumber; DateRangeStart; DateRangeEnd; DOW; - (list) BoardPoint; OffPoint; BoardTime; DateOffSet; OffTime; - ElapsedTime; - (list) CabinCode; Capacity; - SegmentSpecificty (0 or 1); - (list) (optional BoardPoint; OffPoint); CabinCode; Classes - - BA; 9; 2007-04-20; 2007-06-30; 0000011; - LHR; BKK; 22:00; 15:15 / +1; 11:15; F; 5; J; 12; W; 20; Y; 300; - BKK; SYD; 18:10 / +1; 06:05 / +2; 08:55; F; 5; J; 12; W; 20; Y; 300; - 0; F; FA; J; JCDI; W; WT; Y; YBHKMLSQ; - BA; 9; 2007-04-20; 2007-06-30; 1111100; - LHR; BKK; 22:00; 15:15 / +1; 11:15; F; 5; J; 12; W; 20; Y; 300; - BKK; SYD; 18:10 / +1; 06:05 / +2; 08:55; F; 5; J; 12; W; 20; Y; 300; - 1; LHR; BKK; F; FA; J; JCDI; W; WT; Y; YBHKMLSQ; - BKK; SYD; F; FA; J; JCDI; W; WT; Y; YBHKMLSQ; - LHR; SYD; F; FA; J; JCDI; W; WT; Y; YBHKMLSQ; - - Grammar: - DOW ::= int - FlightKey ::= AirlineCode ';' FlightNumber - ';' DateRangeStart ';' DateRangeEnd ';' DOW - LegKey ::= BoardPoint ';' OffPoint - LegDetails ::= BoardTime ['/' BoardDateOffSet] - ';' OffTime ['/' BoardDateOffSet] - ';' Elapsed - LegCabinDetails ::= CabinCode ';' Capacity - Leg ::= LegKey ';' LegDetails (';' CabinDetails)+ - SegmentKey ::= BoardPoint ';' OffPoint - SegmentCabinDetails ::= CabinCode ';' Classes - FullSegmentCabinDetails::= (';' SegmentCabinDetails)+ - GeneralSegments ::= '0' (';' SegmentCabinDetails)+ - SpecificSegments ::= '1' (';' SegmentKey - ';' FullSegmentCabinDetails)+ - Segment ::= GeneralSegment | SpecificSegment - FlightPeriod ::= FlightKey (';' Leg)+ - (';' Segment)+ ';' EndOfFlight - EndOfFlight ::= ';' - */ - -using namespace boost::spirit::classic; - -/** Grammar for the Flight-Period parser. */ -struct FlightPeriodParser : - public boost::spirit::classic::grammar<FlightPeriodParser> { - - FlightPeriodParser (FlightPeriod_T& ioFlightPeriod) - : _flightPeriod (ioFlightPeriod) { - } - - template <typename ScannerT> - struct definition { - definition (FlightPeriodParser const& self) { - - flight_period_list = *( boost::spirit::classic::comment_p("//") - | boost::spirit::classic::comment_p("/*", "*/") - | flight_period ) - ; + flight_number = uint1_4_p; - flight_period = flight_key - >> +( ';' >> leg ) - >> +( ';' >> segment ) - >> flight_period_end[do_end_flight(self._flightPeriod)] + date = lexeme[ uint4_p + >> '-' >> uint2_p + >> '-' >> uint2_p ] ; - flight_period_end = - boost::spirit::classic::ch_p(';') + dow = + lexeme[ repeat(7)[char_("0-1")] ] ; - - flight_key = airline_code - >> ';' >> flight_number - >> ';' >> date[store_date_range_start(self._flightPeriod)] - >> ';' >> date[store_date_range_end(self._flightPeriod)] - >> ';' >> dow[store_dow(self._flightPeriod)] - ; - airline_code = - lexeme_d[ (repeat_p(2,3)[chset_p("0-9A-Z")])[store_airline_code(self._flightPeriod)] ] + leg_list = +(leg); + + leg = leg_key + >> leg_details + >> +(cabin_details) ; - - flight_number = - lexeme_d[ limit_d(0u, 9999u)[uint1_4_p][store_flight_number(self._flightPeriod)] ] - ; - - date = - lexeme_d[ limit_d(2000u,2099u)[uint4_p][assign_a(self._flightPeriod._itYear)] - >> '-' >> limit_d(1u,12u)[uint2_p][assign_a(self._flightPeriod._itMonth)] - >> '-' >> limit_d(1u,31u)[uint2_p][assign_a(self._flightPeriod._itDay)] ] - ; - - dow = - lexeme_d[ repeat_p(7)[chset_p("0-1")] ] - ; - - leg = leg_key >> ';' >> leg_details >> +( ';' >> cabin_details ) - ; - leg_key = - (repeat_p(3)[chset_p("0-9A-Z")])[store_board_point(self._flightPeriod)] - >> ';' - >> (repeat_p(3)[chset_p("0-9A-Z")])[store_off_point(self._flightPeriod)] - ; + leg_key = + lexeme[ repeat(3)[char_("A-Z")] ] + >> ';' + >> lexeme[ repeat(3)[char_("A-Z")] ] + >> ';' + ; - leg_details = - time[store_board_time(self._flightPeriod)] - >> !(date_offset) - >> ';' - >> time[store_off_time(self._flightPeriod)] - >> !(date_offset) - >> ';' - >> time[store_elapsed_time(self._flightPeriod)] - ; + leg_details = + time + >> ';' >> time + >> ';' >> time + >> ';' + ; - time = lexeme_d[ limit_d(0u,23u)[uint2_p][assign_a(self._flightPeriod._itHours)] - >> ':' >> limit_d(0u,59u)[uint2_p][assign_a(self._flightPeriod._itMinutes)] - >> !(':' >> limit_d(0u,59u)[uint2_p][assign_a(self._flightPeriod._itSeconds)]) ] - ; + time = lexeme[ uint2_p + >> ':' >> uint2_p + >> !(':' >> uint2_p) ] + ; + + cabin_details = char_("A-Z") [store_cabin_code_t(_t)] + >> ';' >> double_ + >> ';' + ; - date_offset = - boost::spirit::classic::ch_p('/') - >> (int1_p)[boost::spirit::classic::assign_a(self._flightPeriod._dateOffSet)] - ; - - cabin_details = (chset_p("A-Z"))[store_cabin_code(self._flightPeriod)] - >> ';' >> (boost::spirit::classic::ureal_p)[store_capacity(self._flightPeriod)] - ; - - segment_key = - (repeat_p(3)[chset_p("0-9A-Z")])[store_segment_board_point(self._fl... [truncated message content] |