position_iterator.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*=============================================================================
  2. Copyright (c) 2002 Juan Carlos Arevalo-Baeza
  3. http://spirit.sourceforge.net/
  4. Use, modification and distribution is subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. ///////////////////////////////////////////////////////////////////////////////
  9. //
  10. // A parser for a comma separated list of numbers,
  11. // with positional error reporting
  12. // See the "Position Iterator" chapter in the User's Guide.
  13. //
  14. // [ JCAB 9/28/2002 ]
  15. //
  16. ///////////////////////////////////////////////////////////////////////////////
  17. #include <boost/spirit/include/classic_core.hpp>
  18. #include <boost/spirit/include/classic_position_iterator.hpp>
  19. #include <boost/spirit/include/classic_functor_parser.hpp>
  20. #include <iostream>
  21. #include <fstream>
  22. #include <vector>
  23. ///////////////////////////////////////////////////////////////////////////////
  24. using namespace std;
  25. using namespace BOOST_SPIRIT_CLASSIC_NS;
  26. ///////////////////////////////////////////////////////////////////////////////
  27. //
  28. // Our error reporting parsers
  29. //
  30. ///////////////////////////////////////////////////////////////////////////////
  31. std::ostream& operator<<(std::ostream& out, file_position const& lc)
  32. {
  33. return out <<
  34. "\nFile:\t" << lc.file <<
  35. "\nLine:\t" << lc.line <<
  36. "\nCol:\t" << lc.column << endl;
  37. }
  38. struct error_report_parser {
  39. char const* eol_msg;
  40. char const* msg;
  41. error_report_parser(char const* eol_msg_, char const* msg_):
  42. eol_msg(eol_msg_),
  43. msg (msg_)
  44. {}
  45. typedef nil_t result_t;
  46. template <typename ScannerT>
  47. int
  48. operator()(ScannerT const& scan, result_t& /*result*/) const
  49. {
  50. if (scan.at_end()) {
  51. if (eol_msg) {
  52. file_position fpos = scan.first.get_position();
  53. cerr << fpos << eol_msg << endl;
  54. }
  55. } else {
  56. if (msg) {
  57. file_position fpos = scan.first.get_position();
  58. cerr << fpos << msg << endl;
  59. }
  60. }
  61. return -1; // Fail.
  62. }
  63. };
  64. typedef functor_parser<error_report_parser> error_report_p;
  65. error_report_p
  66. error_badnumber_or_eol =
  67. error_report_parser(
  68. "Expecting a number, but found the end of the file\n",
  69. "Expecting a number, but found something else\n"
  70. );
  71. error_report_p
  72. error_badnumber =
  73. error_report_parser(
  74. 0,
  75. "Expecting a number, but found something else\n"
  76. );
  77. error_report_p
  78. error_comma =
  79. error_report_parser(
  80. 0,
  81. "Expecting a comma, but found something else\n"
  82. );
  83. ///////////////////////////////////////////////////////////////////////////////
  84. //
  85. // Our comma separated list parser
  86. //
  87. ///////////////////////////////////////////////////////////////////////////////
  88. bool
  89. parse_numbers(char const* filename, char const* str, vector<double>& v)
  90. {
  91. typedef position_iterator<char const*> iterator_t;
  92. iterator_t begin(str, str + strlen(str), filename);
  93. iterator_t end;
  94. begin.set_tabchars(8);
  95. return parse(begin, end,
  96. // Begin grammar
  97. (
  98. (real_p[push_back_a(v)] | error_badnumber)
  99. >> *(
  100. (',' | error_comma)
  101. >> (real_p[push_back_a(v)] | error_badnumber_or_eol)
  102. )
  103. )
  104. ,
  105. // End grammar
  106. space_p).full;
  107. }
  108. ////////////////////////////////////////////////////////////////////////////
  109. //
  110. // Main program
  111. //
  112. ////////////////////////////////////////////////////////////////////////////
  113. int
  114. main(int argc, char **argv)
  115. {
  116. cout << "/////////////////////////////////////////////////////////\n\n";
  117. cout << "\tAn error-reporting parser for Spirit...\n\n";
  118. cout << "Parses a comma separated list of numbers from a file.\n";
  119. cout << "The numbers will be inserted in a vector of numbers\n\n";
  120. cout << "/////////////////////////////////////////////////////////\n\n";
  121. char str[65536];
  122. char const* filename;
  123. if (argc > 1) {
  124. filename = argv[1];
  125. ifstream file(filename);
  126. file.get(str, sizeof(str), '\0');
  127. } else {
  128. filename = "<cin>";
  129. cin.get(str, sizeof(str), '\0');
  130. }
  131. vector<double> v;
  132. if (parse_numbers(filename, str, v))
  133. {
  134. cout << "-------------------------\n";
  135. cout << "Parsing succeeded\n";
  136. cout << str << " Parses OK: " << endl;
  137. for (vector<double>::size_type i = 0; i < v.size(); ++i)
  138. cout << i << ": " << v[i] << endl;
  139. cout << "-------------------------\n";
  140. }
  141. else
  142. {
  143. cout << "-------------------------\n";
  144. cout << "Parsing failed\n";
  145. cout << "-------------------------\n";
  146. }
  147. cout << "Bye... :-) \n\n";
  148. return 0;
  149. }