options.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. http://spirit.sourceforge.net/
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. =============================================================================*/
  7. #include <boost/spirit/include/qi.hpp>
  8. #include <boost/spirit/include/karma.hpp>
  9. #include <boost/fusion/include/adapt_struct.hpp>
  10. #include <boost/spirit/repository/include/qi_kwd.hpp>
  11. #include <boost/spirit/repository/include/qi_keywords.hpp>
  12. #include <boost/optional.hpp>
  13. #include <boost/cstdint.hpp>
  14. #include <iostream>
  15. #include <string>
  16. #include <cstdlib>
  17. #include <iterator>
  18. #include <map>
  19. #include <vector>
  20. // Data structure definitions
  21. // preprocessor constants
  22. typedef std::pair<std::string, boost::int32_t> preprocessor_symbol;
  23. BOOST_FUSION_ADAPT_STRUCT( preprocessor_symbol,
  24. (std::string, first)
  25. (boost::int32_t, second)
  26. )
  27. // A data structure to store our program options
  28. struct program_options {
  29. std::vector<std::string> includes; // include paths
  30. typedef std::vector< preprocessor_symbol > preprocessor_symbols_container; // symbol container type definition
  31. preprocessor_symbols_container preprocessor_symbols; // preprocessor symbols
  32. boost::optional<std::string> output_filename; // output file name
  33. std::string source_filename; // source file name
  34. };
  35. // Make the program_options compatible with fusion sequences
  36. BOOST_FUSION_ADAPT_STRUCT( program_options,
  37. (std::vector<std::string>, includes)
  38. (program_options::preprocessor_symbols_container, preprocessor_symbols)
  39. (boost::optional<std::string>, output_filename)
  40. (std::string, source_filename)
  41. )
  42. // Output helper to check that the data parsed matches what we expect
  43. std::ostream &operator<<(std::ostream &os, const program_options &obj)
  44. {
  45. using boost::spirit::karma::string;
  46. using boost::spirit::karma::int_;
  47. using boost::spirit::karma::lit;
  48. using boost::spirit::karma::buffer;
  49. using boost::spirit::karma::eol;
  50. using boost::spirit::karma::format;
  51. return os<<format(
  52. lit("Includes:") << (string % ',') << eol
  53. << lit("Preprocessor symbols:") << ((string <<"="<< int_) % ',') << eol
  54. << buffer[-( lit("Output file:")<< string << eol)]
  55. << lit("Source file:")<< string << eol
  56. ,obj);
  57. return os;
  58. }
  59. int
  60. main()
  61. {
  62. {
  63. // Pull everything we need from qi into this scope
  64. using boost::spirit::repository::qi::kwd;
  65. using boost::spirit::qi::inf;
  66. using boost::spirit::ascii::space_type;
  67. using boost::spirit::ascii::alnum;
  68. using boost::spirit::qi::int_;
  69. using boost::spirit::qi::rule;
  70. using boost::spirit::qi::lit;
  71. using boost::spirit::qi::attr;
  72. using boost::spirit::qi::lexeme;
  73. using boost::spirit::qi::hold;
  74. using boost::spirit::qi::ascii::space;
  75. //Rule declarations
  76. rule<const char *, std::string(), space_type> parse_string;
  77. rule<const char *, program_options(), space_type> kwd_rule;
  78. // A string parser
  79. parse_string %= lexeme[*alnum];
  80. namespace phx=boost::phoenix;
  81. // kwd rule
  82. kwd_rule %=
  83. kwd("--include")[ parse_string ]
  84. / kwd("--define")[ parse_string >> ((lit('=') > int_) | attr(1)) ]
  85. / kwd("--output",0,1)[ parse_string ]
  86. / hold [kwd("--source",1)[ parse_string ]]
  87. ;
  88. //
  89. using boost::spirit::qi::phrase_parse;
  90. // Let's check what that parser can do
  91. program_options result;
  92. char const input[]="--include path1 --source file1 --define SYMBOL1=10 --include path2 --source file2";
  93. char const* f(input);
  94. char const* l(f + strlen(f));
  95. if (phrase_parse(f, l, kwd_rule, space,result) && (f == l))
  96. std::cout << "ok" << std::endl;
  97. else
  98. std::cout << "fail" << std::endl;
  99. // Output the result to the console
  100. std::cout<<result<<std::endl;
  101. }
  102. return 0;
  103. }