AirSched Logo  0.1.4
C++ Simulated Airline Schedule Manager Library
BookingRequestParser.cpp
Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 #include <sstream>
00007 #include <fstream>
00008 // Boost (Extended STL)
00009 #include <boost/date_time/posix_time/posix_time.hpp>
00010 #include <boost/date_time/gregorian/gregorian.hpp>
00011 // Boost Spirit (Parsing)
00012 #define BOOST_SPIRIT_DEBUG
00013 #include <boost/spirit/home/classic/core.hpp>
00014 #include <boost/spirit/home/classic/attribute.hpp>
00015 #include <boost/spirit/home/classic/utility/functor_parser.hpp>
00016 #include <boost/spirit/home/classic/utility/loops.hpp>
00017 #include <boost/spirit/home/classic/utility/chset.hpp>
00018 #include <boost/spirit/home/classic/utility/confix.hpp>
00019 #include <boost/spirit/home/classic/iterator/file_iterator.hpp>
00020 #include <boost/spirit/home/classic/actor/push_back_actor.hpp>
00021 #include <boost/spirit/home/classic/actor/assign_actor.hpp>
00022 // StdAir
00023 #include <stdair/service/Logger.hpp>
00024 // AirSched
00025 #include <airsched/batches/BookingRequestParser.hpp>
00026 
00027 // Type definitions
00028 typedef char char_t;
00029 typedef char const* iterator_t;
00030 //typedef boost::spirit::classic::file_iterator<char_t> iterator_t;
00031 typedef boost::spirit::classic::scanner<iterator_t> scanner_t;
00032 typedef boost::spirit::classic::rule<scanner_t> rule_t;
00033 
00034 namespace airsched {
00035   
00037   struct store_place_element {
00039     store_place_element (SearchString_T& ioSearchString)
00040       : _searchString (ioSearchString) {}
00041 
00043     void operator() (iterator_t iStr, iterator_t iStrEnd) const {
00044       std::string lPlace (iStr, iStrEnd);
00045       // std::cout << "Place: " << lPlace << std::endl;
00046       
00047       // Set the place
00048       _searchString._tmpPlace._name += " " + lPlace;
00049       
00050       // Add the parsed place to the list
00051       // _searchString._placeList.push_back (_searchString._tmpPlace);
00052     }
00053     
00054     SearchString_T& _searchString;
00055   };
00056   
00058   struct store_date {
00060     store_date (SearchString_T& ioSearchString)
00061       : _searchString (ioSearchString) {}
00062     
00064     void operator() (iterator_t iStr, iterator_t iStrEnd) const {
00065       _searchString._tmpDate._date = _searchString._tmpDate.getDate();
00066       // std::cout << "Board date: "
00067       // << _searchString._date << std::endl;
00068     
00069       // Add the parsed date to the list
00070       _searchString._dateList.push_back (_searchString._tmpDate);
00071     }
00072     
00073     SearchString_T& _searchString;
00074   };
00075 
00077   struct store_airline_sign {
00079     store_airline_sign (SearchString_T& ioSearchString)
00080       : _searchString (ioSearchString) {}
00081 
00083     void operator() (bool iAirlineSign) const {
00084       _searchString._tmpAirline._isPreferred = !iAirlineSign;
00085       // std::cout << "Airline is preferred: " << iAirlineSign << std::endl;
00086     }
00087     
00088     SearchString_T& _searchString;
00089   };
00090   
00092   struct store_airline_code {
00094     store_airline_code (SearchString_T& ioSearchString)
00095       : _searchString (ioSearchString) {}
00096     
00098     void operator() (iterator_t iStr, iterator_t iStrEnd) const {
00099       std::string lAirlineCode (iStr, iStrEnd);
00100       _searchString._tmpAirline._code = lAirlineCode;
00101       // std::cout << "Airline code: " << lAirlineCode << std::endl;
00102       
00103       // Add the parsed airline to the list
00104       _searchString._airlineList.push_back (_searchString._tmpAirline);
00105     }
00106     
00107     SearchString_T& _searchString;
00108   };
00109   
00111   struct store_airline_name {
00113     store_airline_name (SearchString_T& ioSearchString)
00114       : _searchString (ioSearchString) {}
00115     
00117     void operator() (iterator_t iStr, iterator_t iStrEnd) const {
00118       std::string lAirlineName (iStr, iStrEnd);
00119       _searchString._tmpAirline._name = lAirlineName;
00120       // std::cout << "Airline: " << lAirlineName << std::endl;
00121       
00122       // Add the parsed airline to the list
00123       _searchString._airlineList.push_back (_searchString._tmpAirline);
00124     }
00125     
00126     SearchString_T& _searchString;
00127   };
00128   
00130   struct store_passenger_number {
00132     store_passenger_number (SearchString_T& ioSearchString)
00133       : _searchString (ioSearchString) {}
00134 
00136     void operator() (unsigned int iNumber) const {
00137       _searchString._tmpPassenger._number = iNumber;
00138       // std::cout << "Number of passengers: " << iNumber << std::endl;
00139     }
00140     
00141     SearchString_T& _searchString;
00142   };
00143   
00145   struct store_adult_passenger_type {
00147     store_adult_passenger_type (SearchString_T& ioSearchString)
00148       : _searchString (ioSearchString) {}
00149     
00151     void operator() (iterator_t iStr, iterator_t iStrEnd) const {
00152       std::string lPassengerType (iStr, iStrEnd);
00153       _searchString._tmpPassenger._type = Passenger_T::ADULT;
00154       // std::cout << "Passenger type: " << lPassengerType << std::endl;
00155       
00156       // Add the parsed passenger to the list
00157       _searchString._passengerList.push_back (_searchString._tmpPassenger);
00158     }
00159     
00160     SearchString_T& _searchString;
00161   };
00162   
00164   struct store_child_passenger_type {
00166     store_child_passenger_type (SearchString_T& ioSearchString)
00167       : _searchString (ioSearchString) {}
00168     
00170     void operator() (iterator_t iStr, iterator_t iStrEnd) const {
00171       std::string lPassengerType (iStr, iStrEnd);
00172       _searchString._tmpPassenger._type = Passenger_T::CHILD;
00173       // std::cout << "Passenger type: " << lPassengerType << std::endl;
00174       
00175       // Add the parsed passenger to the list
00176       _searchString._passengerList.push_back (_searchString._tmpPassenger);
00177     }
00178     
00179     SearchString_T& _searchString;
00180   };
00181   
00183   struct store_pet_passenger_type {
00185     store_pet_passenger_type (SearchString_T& ioSearchString)
00186       : _searchString (ioSearchString) {}
00187 
00189     void operator() (iterator_t iStr, iterator_t iStrEnd) const {
00190       std::string lPassengerType (iStr, iStrEnd);
00191       _searchString._tmpPassenger._type = Passenger_T::PET;
00192       // std::cout << "Passenger type: " << lPassengerType << std::endl;
00193       
00194       // Add the parsed passenger to the list
00195       _searchString._passengerList.push_back (_searchString._tmpPassenger);
00196     }
00197     
00198     SearchString_T& _searchString;
00199   };
00200 
00201   // /////////// Utilities /////////////
00203   boost::spirit::classic::int_parser<unsigned int, 10, 1, 1> int1_p;
00205   boost::spirit::classic::uint_parser<unsigned int, 10, 1, 1> uint1_p;
00207   boost::spirit::classic::uint_parser<unsigned int, 10, 1, 2> uint1_2_p;
00209   boost::spirit::classic::uint_parser<int, 10, 2, 2> uint2_p;
00211   boost::spirit::classic::uint_parser<int, 10, 2, 4> uint2_4_p;
00213   boost::spirit::classic::uint_parser<int, 10, 4, 4> uint4_p;
00215   boost::spirit::classic::uint_parser<int, 10, 1, 4> uint1_4_p;
00216 
00218   //
00219   //  Our calculator grammar (using subrules)
00220   //
00222 
00248   using namespace boost::spirit::classic;
00249 
00251   struct SearchStringParser : 
00252     public boost::spirit::classic::grammar<SearchStringParser> {
00253 
00254     SearchStringParser (SearchString_T& ioSearchString) 
00255       : _searchString (ioSearchString) {
00256     }
00257 
00258     template <typename ScannerT>
00259     struct definition {
00260       definition (SearchStringParser const& self) {
00261 
00262         search_string = places
00263           >> !( dates )
00264           >> *( preferred_airlines )
00265           >> *( passengers )
00266           ;
00267 
00268         places =
00269           +( place_element )
00270           ;
00271 
00272         place_element =
00273           lexeme_d[ (repeat_p(1,20)[chset_p("a-z")])[store_place_element(self._searchString)] ]
00274           ;
00275       
00276         dates =
00277           date[store_date(self._searchString)]
00278           >> !date[store_date(self._searchString)]
00279           ;
00280       
00281         date =
00282           ( month | day )
00283           >> boost::spirit::classic::chset_p("/-")
00284           >> ( day | month )
00285           >> ! ( boost::spirit::classic::chset_p("/-")
00286                  >> year )
00287           ;
00288 
00289         day =
00290           lexeme_d[ limit_d(1u,31u)[uint1_2_p][assign_a(self._searchString._tmpDate._day)] ]
00291           ;
00292         
00293         month =
00294           lexeme_d[ limit_d(1u,12u)[uint1_2_p][assign_a(self._searchString._tmpDate._month)] ]
00295           ;
00296 
00297         year =
00298           lexeme_d[ limit_d(2000u,2099u)[uint4_p][assign_a(self._searchString._tmpDate._year)] ]
00299           | lexeme_d[ limit_d(0u,99u)[uint2_p][assign_a(self._searchString._tmpDate._year)] ]
00300           ;
00301 
00302         preferred_airlines =
00303           !(boost::spirit::classic::sign_p)[store_airline_sign(self._searchString)]
00304           >> airline_code | airline_name
00305           ;
00306 
00307         airline_code =
00308           lexeme_d[ (repeat_p(2,3)[chset_p("0-9a-z")])[store_airline_code(self._searchString)] ]
00309           ;
00310       
00311         airline_name =
00312           lexeme_d[ (repeat_p(4,20)[chset_p("0-9a-z")])[store_airline_name(self._searchString)] ]
00313           ;
00314 
00315         passengers =
00316           passenger_number >> passenger_type
00317           ;
00318       
00319         passenger_number =
00320           lexeme_d[ limit_d(1u, 9u)[uint1_p][store_passenger_number(self._searchString)] ]
00321           ;
00322 
00323         passenger_type =
00324           passenger_adult_type[store_adult_passenger_type(self._searchString)]
00325           | passenger_child_type[store_child_passenger_type(self._searchString)]
00326           | passenger_pet_type[store_pet_passenger_type(self._searchString)]
00327           ;
00328 
00329         passenger_adult_type =
00330           lexeme_d[ as_lower_d [ str_p("adult") >> !ch_p('s') ] ]
00331           ;
00332       
00333         passenger_child_type =
00334           lexeme_d[ as_lower_d [ str_p("child") >> !str_p("ren") ] ]
00335           ;
00336       
00337         passenger_pet_type =
00338           lexeme_d[ as_lower_d [ str_p("dog") | str_p("cat") >> !ch_p('s') ] ]
00339           ;
00340       
00341         BOOST_SPIRIT_DEBUG_NODE (search_string);
00342         BOOST_SPIRIT_DEBUG_NODE (places);
00343         BOOST_SPIRIT_DEBUG_NODE (place_element);
00344         BOOST_SPIRIT_DEBUG_NODE (dates);
00345         BOOST_SPIRIT_DEBUG_NODE (date);
00346         BOOST_SPIRIT_DEBUG_NODE (day);
00347         BOOST_SPIRIT_DEBUG_NODE (month);
00348         BOOST_SPIRIT_DEBUG_NODE (year);
00349         BOOST_SPIRIT_DEBUG_NODE (preferred_airlines);
00350         BOOST_SPIRIT_DEBUG_NODE (airline_code);
00351         BOOST_SPIRIT_DEBUG_NODE (airline_name);
00352         BOOST_SPIRIT_DEBUG_NODE (passengers);
00353         BOOST_SPIRIT_DEBUG_NODE (passenger_number);
00354         BOOST_SPIRIT_DEBUG_NODE (passenger_type);
00355         BOOST_SPIRIT_DEBUG_NODE (passenger_adult_type);
00356         BOOST_SPIRIT_DEBUG_NODE (passenger_child_type);
00357         BOOST_SPIRIT_DEBUG_NODE (passenger_pet_type);
00358       }
00359     
00360       boost::spirit::classic::rule<ScannerT> search_string, places, place_element,
00361         dates, date, month, day, year,
00362         preferred_airlines, airline_code, airline_name,
00363         passengers, passenger_number, passenger_type, passenger_adult_type,
00364         passenger_child_type, passenger_pet_type;
00365 
00366       boost::spirit::classic::rule<ScannerT> const& start() const { return search_string; }
00367     };
00368 
00369     SearchString_T& _searchString;
00370   };
00371 
00372   // //////////////////////////////////////////////////////////
00373   SearchString_T parseBookingRequest (const std::string& iSearchString) {
00374     SearchString_T oSearchStringStruct;
00375   
00376     // Read the search string
00377     iterator_t lStringIterator = iSearchString.c_str();
00378 
00379     // Instantiate the structure that will hold the result of the parsing.
00380     SearchStringParser lSearchStringParser (oSearchStringStruct);
00381     boost::spirit::classic::parse_info<iterator_t> info =
00382       boost::spirit::classic::parse (lStringIterator, lSearchStringParser, 
00383                                      boost::spirit::classic::space_p);
00384   
00385     STDAIR_LOG_DEBUG ("-------------------------");
00386   
00387     bool hasBeenParsingSuccessful = info.full;
00388     if (hasBeenParsingSuccessful == true) {
00389       STDAIR_LOG_DEBUG ("Parsing succeeded");
00390     
00391     } else {
00392       STDAIR_LOG_DEBUG ("Parsing failed");
00393     }
00394     STDAIR_LOG_DEBUG ("-------------------------");
00395   
00396     return oSearchStringStruct;
00397   }
00398 
00399 }