| /*============================================================================= |
| Copyright (c) 2001-2011 Joel de Guzman |
| http://spirit.sourceforge.net/ |
| |
| 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/spirit/include/qi.hpp> |
| #include <boost/spirit/include/karma.hpp> |
| #include <boost/fusion/include/adapt_struct.hpp> |
| #include <boost/spirit/repository/include/qi_kwd.hpp> |
| #include <boost/spirit/repository/include/qi_keywords.hpp> |
| #include <boost/optional.hpp> |
| #include <boost/cstdint.hpp> |
| #include <iostream> |
| #include <string> |
| #include <cstdlib> |
| #include <iterator> |
| #include <map> |
| #include <vector> |
| |
| // Data structure definitions |
| |
| // preprocessor constants |
| typedef std::pair<std::string, boost::int32_t> preprocessor_symbol; |
| |
| BOOST_FUSION_ADAPT_STRUCT( preprocessor_symbol, |
| (std::string, first) |
| (boost::int32_t, second) |
| ) |
| |
| // A data structure to store our program options |
| struct program_options { |
| std::vector<std::string> includes; // include paths |
| typedef std::vector< preprocessor_symbol > preprocessor_symbols_container; // symbol container type definition |
| preprocessor_symbols_container preprocessor_symbols; // preprocessor symbols |
| boost::optional<std::string> output_filename; // output file name |
| std::string source_filename; // source file name |
| |
| }; |
| |
| // Make the program_options compatible with fusion sequences |
| BOOST_FUSION_ADAPT_STRUCT( program_options, |
| (std::vector<std::string>, includes) |
| (program_options::preprocessor_symbols_container, preprocessor_symbols) |
| (boost::optional<std::string>, output_filename) |
| (std::string, source_filename) |
| ) |
| |
| |
| // Output helper to check that the data parsed matches what we expect |
| std::ostream &operator<<(std::ostream &os, const program_options &obj) |
| { |
| using boost::spirit::karma::string; |
| using boost::spirit::karma::int_; |
| using boost::spirit::karma::lit; |
| using boost::spirit::karma::buffer; |
| using boost::spirit::karma::eol; |
| using boost::spirit::karma::format; |
| return os<<format( |
| lit("Includes:") << (string % ',') << eol |
| << lit("Preprocessor symbols:") << ((string <<"="<< int_) % ',') << eol |
| << buffer[-( lit("Output file:")<< string << eol)] |
| << lit("Source file:")<< string << eol |
| ,obj); |
| return os; |
| } |
| |
| |
| int |
| main() |
| { |
| |
| { |
| // Pull everything we need from qi into this scope |
| using boost::spirit::repository::qi::kwd; |
| using boost::spirit::qi::inf; |
| using boost::spirit::ascii::space_type; |
| using boost::spirit::ascii::alnum; |
| using boost::spirit::qi::int_; |
| using boost::spirit::qi::rule; |
| using boost::spirit::qi::lit; |
| using boost::spirit::qi::attr; |
| using boost::spirit::qi::lexeme; |
| using boost::spirit::qi::hold; |
| using boost::spirit::qi::ascii::space; |
| |
| //Rule declarations |
| rule<const char *, std::string(), space_type> parse_string; |
| rule<const char *, program_options(), space_type> kwd_rule; |
| |
| // A string parser |
| parse_string %= lexeme[*alnum]; |
| |
| namespace phx=boost::phoenix; |
| // kwd rule |
| kwd_rule %= |
| kwd("--include")[ parse_string ] |
| / kwd("--define")[ parse_string >> ((lit('=') > int_) | attr(1)) ] |
| / kwd("--output",0,1)[ parse_string ] |
| / hold [kwd("--source",1)[ parse_string ]] |
| ; |
| // |
| |
| using boost::spirit::qi::phrase_parse; |
| |
| // Let's check what that parser can do |
| program_options result; |
| |
| char const input[]="--include path1 --source file1 --define SYMBOL1=10 --include path2 --source file2"; |
| char const* f(input); |
| char const* l(f + strlen(f)); |
| if (phrase_parse(f, l, kwd_rule, space,result) && (f == l)) |
| std::cout << "ok" << std::endl; |
| else |
| std::cout << "fail" << std::endl; |
| |
| // Output the result to the console |
| std::cout<<result<<std::endl; |
| } |
| return 0; |
| } |