| /*============================================================================= |
| Copyright (c) 2016 Frank Hein, maxence business consulting gmbh |
| |
| 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 <iostream> |
| #include <map> |
| |
| #include <boost/spirit/home/qi.hpp> |
| #include <boost/spirit/home/qi/nonterminal/grammar.hpp> |
| #include <boost/spirit/include/phoenix.hpp> |
| #include <boost/foreach.hpp> |
| |
| namespace qi = boost::spirit::qi; |
| |
| typedef std::string::const_iterator iterator_type; |
| typedef std::string result_type; |
| |
| template<typename Parser> |
| void parse(const std::string message, const std::string& input, const std::string& rule, const Parser& parser) { |
| iterator_type iter = input.begin(), end = input.end(); |
| |
| std::vector<result_type> parsed_result; |
| |
| std::cout << "-------------------------\n"; |
| std::cout << message << "\n"; |
| std::cout << "Rule: " << rule << std::endl; |
| std::cout << "Parsing: \"" << input << "\"\n"; |
| |
| bool result = qi::phrase_parse(iter, end, parser, qi::space, parsed_result); |
| if (result) |
| { |
| std::cout << "Parser succeeded.\n"; |
| std::cout << "Parsed " << parsed_result.size() << " elements:"; |
| BOOST_FOREACH(result_type const& str, parsed_result) |
| { |
| std::cout << "[" << str << "]"; |
| } |
| std::cout << std::endl; |
| } |
| else |
| { |
| std::cout << "Parser failed" << std::endl; |
| } |
| if (iter == end) { |
| std::cout << "EOI reached." << std::endl; |
| } |
| else { |
| std::cout << "EOI not reached. Unparsed: \"" << std::string(iter, end) << "\"" << std::endl; |
| } |
| std::cout << "-------------------------\n"; |
| |
| } |
| |
| namespace grammars { |
| namespace phx = boost::phoenix; |
| |
| template <typename Iterator> |
| struct ident : qi::grammar < Iterator, std::string(), qi::space_type> |
| { |
| ident(); |
| |
| qi::rule <iterator_type, std::string(), qi::space_type> |
| id, id_list, qualified_id; |
| }; |
| |
| template <typename Iterator> |
| ident<Iterator>::ident() : ident::base_type(id_list) { |
| |
| using qi::on_error; |
| using qi::fail; |
| using qi::expect; |
| |
| id = (qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_')); |
| |
| id_list = expect[id >> qi::lit(';')]; |
| |
| on_error<fail>(id_list, |
| phx::ref(std::cout) |
| << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl |
| << "Error! Expecting " |
| << qi::_4 |
| << " here: " |
| << phx::construct<std::string>(qi::_3, qi::_2) << std::endl |
| << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl |
| ); |
| } |
| } |
| |
| int main() { |
| |
| grammars::ident<iterator_type> id; |
| |
| parse("expect directive, fail on first" |
| , "1234; id2;" |
| , "qi::expect[ id >> qi::lit(';') ]" |
| , id); |
| |
| parse("expect directive, fail on second" |
| , "id1, id2" |
| , "qi::expect[ id >> qi::lit(';') ]" |
| , id); |
| |
| parse("expect directive, success" |
| , "id1;" |
| , "qi::expect[ id >> qi::lit(';') ]" |
| , id); |
| |
| return 0; |
| } |