ERMParser.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include "ERMParser.h"
  2. #include <boost/spirit/include/qi.hpp>
  3. #include <boost/bind.hpp>
  4. #include <boost/spirit/include/phoenix_core.hpp>
  5. #include <boost/spirit/include/phoenix_operator.hpp>
  6. #include <boost/spirit/include/phoenix_fusion.hpp>
  7. #include <boost/spirit/include/phoenix_stl.hpp>
  8. #include <boost/spirit/include/phoenix_object.hpp>
  9. #include <fstream>
  10. namespace spirit = boost::spirit;
  11. namespace qi = boost::spirit::qi;
  12. ERMParser::ERMParser(std::string file)
  13. :srcFile(file)
  14. {}
  15. void ERMParser::parseFile()
  16. {
  17. std::ifstream file(srcFile);
  18. if(!file.is_open())
  19. {
  20. tlog1 << "File " << srcFile << " not found or unable to open\n";
  21. return;
  22. }
  23. //check header
  24. char header[5];
  25. file.getline(header, ARRAY_COUNT(header));
  26. if(std::string(header) != "ZVSE")
  27. {
  28. tlog1 << "File " << srcFile << " has wrong header\n";
  29. return;
  30. }
  31. //parse file
  32. char lineBuf[1024];
  33. int lineNum = 1;
  34. while(file.good())
  35. {
  36. //reading line
  37. file.getline(lineBuf, ARRAY_COUNT(lineBuf));
  38. if(file.gcount() == ARRAY_COUNT(lineBuf))
  39. {
  40. tlog1 << "Encountered a problem during parsing " << srcFile << " too long line " << lineNum << "\n";
  41. }
  42. //parsing
  43. parseLine(lineBuf);
  44. //loop end
  45. ++lineNum;
  46. }
  47. }
  48. void callme(char const& i)
  49. {
  50. std::cout << "fd";
  51. }
  52. void ERMParser::parseLine( std::string line )
  53. {
  54. namespace ascii = spirit::ascii;
  55. namespace phoenix = boost::phoenix;
  56. typedef std::string::iterator sit;
  57. qi::rule<sit> comment = *(qi::char_);
  58. qi::rule<sit> commentLine = ~qi::char_('!') >> comment;
  59. qi::rule<sit> cmdName = qi::repeat(2)[ascii::alpha];
  60. qi::rule<sit> identifier = qi::int_ % '/';
  61. qi::rule<sit> condition = qi::char_('&') >> +(qi::int_ | qi::char_("a-zA-Z&/|")) >> qi::char_(":;");
  62. qi::rule<sit> trigger = cmdName >> -identifier >> -condition;
  63. qi::rule<sit> string = qi::char_('^') >> ascii::print >> qi::char_('^');
  64. qi::rule<sit> body = *(qi::char_("a-zA-Z0-9/ ") | string);
  65. qi::rule<sit> instruction = cmdName >> -identifier >> -condition >> body;
  66. qi::rule<sit> receiver = cmdName >> -identifier >> -condition >> body;
  67. qi::rule<sit> postOBtrigger = "$OB" >> -identifier >> -condition;
  68. qi::rule<sit> rline =
  69. (
  70. (qi::char_('!') >>
  71. (
  72. (qi::char_('?') >> trigger) |
  73. (qi::char_('!') >> instruction) |
  74. (qi::char_('#') >> receiver) |
  75. postOBtrigger
  76. ) >> comment
  77. )
  78. | commentLine | spirit::eoi
  79. );
  80. qi::on_error<qi::fail>
  81. (
  82. rline
  83. , std::cout //or phoenix::ref(std::count), is there any difference?
  84. << phoenix::val("Error! Expecting ")
  85. << qi::_4 // what failed?
  86. << phoenix::val(" here: \"")
  87. << phoenix::construct<std::string>(qi::_3, qi::_2) // iterators to error-pos, end
  88. << phoenix::val("\"")
  89. << std::endl
  90. );
  91. sit beg = line.begin(),
  92. end = line.end();
  93. bool r = qi::parse(beg, end, rline);
  94. if(!r || beg != end)
  95. {
  96. tlog1 << "Parse error for line " << line << std::endl;
  97. tlog1 << "\tCannot parse: " << std::string(beg, end) << std::endl;
  98. }
  99. }