error_handler.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  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. #if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
  8. #define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
  9. #include <iostream>
  10. #include <string>
  11. #include <vector>
  12. namespace client
  13. {
  14. ///////////////////////////////////////////////////////////////////////////////
  15. // The error handler
  16. ///////////////////////////////////////////////////////////////////////////////
  17. template <typename BaseIterator, typename Iterator>
  18. struct error_handler
  19. {
  20. template <typename, typename, typename>
  21. struct result { typedef void type; };
  22. error_handler(BaseIterator first, BaseIterator last)
  23. : first(first), last(last) {}
  24. template <typename Message, typename What>
  25. void operator()(
  26. Message const& message,
  27. What const& what,
  28. Iterator err_pos) const
  29. {
  30. // retrieve underlying iterator from current token, err_pos points
  31. // to the last validly matched token, so we use its end iterator
  32. // as the error position
  33. BaseIterator err_pos_base = err_pos->matched().end();
  34. std::cout << message << what << std::endl;
  35. if (err_pos_base != BaseIterator())
  36. dump_error_line(err_pos_base);
  37. }
  38. void dump_error_line(BaseIterator err_pos_base) const
  39. {
  40. int line;
  41. BaseIterator line_start = get_pos(err_pos_base, line);
  42. if (err_pos_base != last)
  43. {
  44. std::cout << " line " << line << ':' << std::endl;
  45. std::cout << get_line(line_start) << std::endl;
  46. for (; line_start != err_pos_base; ++line_start)
  47. std::cout << ' ';
  48. std::cout << '^' << std::endl;
  49. }
  50. else
  51. {
  52. std::cout << "Unexpected end of file.\n";
  53. }
  54. }
  55. BaseIterator get_pos(BaseIterator err_pos, int& line) const
  56. {
  57. line = 1;
  58. BaseIterator i = first;
  59. BaseIterator line_start = first;
  60. while (i != err_pos)
  61. {
  62. bool eol = false;
  63. if (i != err_pos && *i == '\r') // CR
  64. {
  65. eol = true;
  66. line_start = ++i;
  67. }
  68. if (i != err_pos && *i == '\n') // LF
  69. {
  70. eol = true;
  71. line_start = ++i;
  72. }
  73. if (eol)
  74. ++line;
  75. else
  76. ++i;
  77. }
  78. return line_start;
  79. }
  80. std::string get_line(BaseIterator err_pos) const
  81. {
  82. BaseIterator i = err_pos;
  83. // position i to the next EOL
  84. while (i != last && (*i != '\r' && *i != '\n'))
  85. ++i;
  86. return std::string(err_pos, i);
  87. }
  88. BaseIterator first;
  89. BaseIterator last;
  90. std::vector<Iterator> iters;
  91. };
  92. }
  93. #endif