|
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] |