fork download
  1. #define BOOST_SPIRIT_USE_PHOENIX_V3
  2. #define BOOST_SPIRIT_DEBUG
  3. #include <boost/spirit/include/qi.hpp>
  4. #include <boost/spirit/include/phoenix.hpp>
  5. #include <boost/fusion/adapted.hpp>
  6. #include <string>
  7. #include <vector>
  8. #include <map>
  9. #include <iostream>
  10. #include <fstream>
  11.  
  12. struct IniSection
  13. {
  14. std::string name;
  15. std::vector<std::string> inherits;
  16. std::vector<std::string> components;
  17. std::map<std::string, std::string> properties;
  18. };
  19.  
  20. typedef std::map<std::string, std::string> Properties;
  21. BOOST_FUSION_ADAPT_STRUCT(
  22. IniSection,
  23. (std::string, name)
  24. (std::vector<std::string>, inherits)
  25. (std::vector<std::string>, components)
  26. (Properties, properties)
  27. )
  28.  
  29. namespace qi = boost::spirit::qi;
  30. namespace phx = boost::phoenix;
  31.  
  32. template<typename Iterator>
  33. struct SkipperWithComments : public qi::grammar<Iterator>
  34. {
  35. qi::rule<Iterator> skip, comment, multi_comment;
  36.  
  37. SkipperWithComments()
  38. : SkipperWithComments::base_type(skip, "skipper grammar")
  39. {
  40. comment = (qi::lit("//") | qi::lit(";") | qi::lit("#")) >> *(qi::char_ - qi::eol) >> qi::eol;
  41. multi_comment = "/*" > *(qi::char_ - "*/") > "*/";
  42. skip = qi::blank | comment | multi_comment;
  43. //BOOST_SPIRIT_DEBUG_NODES((skip)(comment)(multi_comment));
  44. }
  45. };
  46.  
  47. template <typename Iterator, typename Skipper>
  48. struct SectionParser : qi::grammar<Iterator, IniSection(), Skipper>
  49. {
  50. qi::rule<Iterator, IniSection(), Skipper> section;
  51. qi::rule<Iterator, std::string(), Skipper> ident, value;
  52. qi::rule<Iterator, std::vector<std::string>(), Skipper> sectionInherits, components;
  53. qi::rule<Iterator, std::pair<std::string, std::string>(), Skipper> prop;
  54. qi::rule<Iterator, std::map<std::string, std::string>(), Skipper> props;
  55.  
  56. SectionParser()
  57. : SectionParser::base_type(section, "section grammar")
  58. {
  59. ident = +qi::char_("a-zA-Z0-9_");
  60. value = *(qi::char_ - (qi::eol));
  61.  
  62. sectionInherits = qi::lit(':') >> ident % ',';
  63.  
  64. components = *qi::eol >> (qi::as_string[qi::char_('@') >> ident] % +qi::eol);
  65.  
  66. prop = ident >> qi::lit('=') >> value;
  67. props = *qi::eol >> (prop % +qi::eol);
  68.  
  69. section =
  70. qi::lit('[')
  71. >> qi::as_string[-qi::char_("!") >> ident]
  72. >> -sectionInherits
  73. >> qi::lit(']')
  74. >> -components
  75. >> -props;
  76.  
  77. BOOST_SPIRIT_DEBUG_NODES((section)(components)(sectionInherits)(ident)(value)(props)(prop));
  78. }
  79. };
  80.  
  81. template <typename Iterator, typename Skipper>
  82. bool parse_numbers(Iterator first, Iterator last, const Skipper& skipper, std::vector<IniSection>& sections)
  83. {
  84. SectionParser<Iterator, Skipper> sectionParser;
  85.  
  86. try
  87. {
  88. bool ok = qi::phrase_parse(first, last, *qi::eol >> (sectionParser % +qi::eol) >> qi::eoi, skipper, sections);
  89.  
  90. if (first != last)
  91. {
  92. std::cout << "warning, part of input is unparsed: " << std::string(first, last) << std::endl;
  93. return false;
  94. }
  95.  
  96. return ok;
  97. }
  98. catch (qi::expectation_failure<Iterator> const& e)
  99. {
  100. std::cout << "parse error: " << e.what() << ", unparsed: " << std::string(first, last) << std::endl;
  101. return false;
  102. }
  103. }
  104.  
  105. template <typename Iterator>
  106. bool doParse(Iterator first, Iterator last, std::vector<IniSection>& sections)
  107. {
  108. return parse_numbers(first, last, SkipperWithComments<Iterator>(), sections);
  109. }
  110.  
  111. bool parse(const std::string& input, std::vector<IniSection>& out)
  112. {
  113. return doParse(input.begin(), input.end(), out);
  114. }
  115.  
  116. bool parse(boost::spirit::istream_iterator first, boost::spirit::istream_iterator last, std::vector<IniSection>& out)
  117. {
  118. return doParse(first, last, out);
  119. }
  120.  
  121. int main()
  122. {
  123. boost::spirit::istream_iterator begin(std::cin >> std::noskipws);
  124. boost::spirit::istream_iterator end;
  125.  
  126. std::vector<IniSection> sections;
  127. if (parse(begin, end, sections))
  128. {
  129. std::cout << "success!" << std::endl;
  130. return 0;
  131. }
  132.  
  133. std::cout << "fail!" << std::endl;
  134. return -1;
  135. }
Success #stdin #stdout #stderr 0s 3412KB
stdin
[section]
@one
@two
prop=val
prop2=val2
stdout
success!
stderr
<section>
  <try>[section]\n@one\n@two\n</try>
  <ident>
    <try>section]\n@one\n@two\np</try>
    <success>]\n@one\n@two\nprop=val</success>
    <attributes>[[s, e, c, t, i, o, n]]</attributes>
  </ident>
  <sectionInherits>
    <try>]\n@one\n@two\nprop=val</try>
    <fail/>
  </sectionInherits>
  <components>
    <try>\n@one\n@two\nprop=val\n</try>
    <ident>
      <try>one\n@two\nprop=val\npr</try>
      <success>\n@two\nprop=val\nprop2</success>
      <attributes>[[@, o, n, e]]</attributes>
    </ident>
    <ident>
      <try>two\nprop=val\nprop2=v</try>
      <success>\nprop=val\nprop2=val2</success>
      <attributes>[[@, t, w, o]]</attributes>
    </ident>
    <success>\nprop=val\nprop2=val2</success>
    <attributes>[[[@, o, n, e], [@, t, w, o]]]</attributes>
  </components>
  <props>
    <try>\nprop=val\nprop2=val2</try>
    <prop>
      <try>prop=val\nprop2=val2</try>
      <ident>
        <try>prop=val\nprop2=val2</try>
        <success>=val\nprop2=val2</success>
        <attributes>[[p, r, o, p]]</attributes>
      </ident>
      <value>
        <try>val\nprop2=val2</try>
        <success>\nprop2=val2</success>
        <attributes>[[v, a, l]]</attributes>
      </value>
      <success>\nprop2=val2</success>
      <attributes>[[[p, r, o, p], [v, a, l]]]</attributes>
    </prop>
    <prop>
      <try>prop2=val2</try>
      <ident>
        <try>prop2=val2</try>
        <success>=val2</success>
        <attributes>[[p, r, o, p, 2]]</attributes>
      </ident>
      <value>
        <try>val2</try>
        <success></success>
        <attributes>[[v, a, l, 2]]</attributes>
      </value>
      <success></success>
      <attributes>[[[p, r, o, p, 2], [v, a, l, 2]]]</attributes>
    </prop>
    <success></success>
    <attributes>[[[[p, r, o, p], [v, a, l]], [[p, r, o, p, 2], [v, a, l, 2]]]]</attributes>
  </props>
  <success></success>
  <attributes>[[[s, e, c, t, i, o, n], [], [[@, o, n, e], [@, t, w, o]], [[[p, r, o, p], [v, a, l]], [[p, r, o, p, 2], [v, a, l, 2]]]]]</attributes>
</section>