sexpr_parser.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*==============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2010-2011 Bryce Lelbach
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP)
  8. #define BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP
  9. #include "utf8_parser.hpp"
  10. #include "error_handler.hpp"
  11. namespace boost {
  12. namespace spirit {
  13. namespace traits {
  14. template<>
  15. struct transform_attribute<utree::nil_type, unused_type, qi::domain> {
  16. typedef unused_type type;
  17. static unused_type pre (utree::nil_type&) { return unused_type(); }
  18. static void post (utree::nil_type&, unused_type) { }
  19. static void fail (utree::nil_type&) { }
  20. };
  21. } // traits
  22. } // spirit
  23. } // boost
  24. namespace sexpr
  25. {
  26. namespace qi = boost::spirit::qi;
  27. namespace px = boost::phoenix;
  28. namespace standard = boost::spirit::standard;
  29. using boost::spirit::utree;
  30. using boost::spirit::utf8_symbol_type;
  31. using boost::spirit::utf8_string_type;
  32. using boost::spirit::binary_string_type;
  33. struct bool_input_policies
  34. {
  35. template <typename Iterator, typename Attribute>
  36. static bool
  37. parse_true(Iterator& first, Iterator const& last, Attribute& attr)
  38. {
  39. using boost::spirit::qi::detail::string_parse;
  40. using boost::spirit::qi::bool_policies;
  41. using boost::spirit::qi::unused;
  42. using boost::spirit::traits::assign_to;
  43. if (string_parse("#t", first, last, unused))
  44. {
  45. assign_to(true, attr); // result is true
  46. return true;
  47. }
  48. return bool_policies<bool>::parse_true(first, last, attr);
  49. }
  50. template <typename Iterator, typename Attribute>
  51. static bool
  52. parse_false(Iterator& first, Iterator const& last, Attribute& attr)
  53. {
  54. using boost::spirit::qi::detail::string_parse;
  55. using boost::spirit::qi::bool_policies;
  56. using boost::spirit::qi::unused;
  57. using boost::spirit::traits::assign_to;
  58. if (string_parse("#f", first, last, unused))
  59. {
  60. assign_to(false, attr); // result is false
  61. return true;
  62. }
  63. return bool_policies<bool>::parse_false(first, last, attr);
  64. }
  65. };
  66. struct save_line_pos
  67. {
  68. template <typename, typename>
  69. struct result
  70. {
  71. typedef void type;
  72. };
  73. template <typename Range>
  74. void operator()(utree& ast, Range const& rng) const
  75. {
  76. using boost::spirit::get_line;
  77. std::size_t n = get_line(rng.begin());
  78. if (n != -1)
  79. {
  80. BOOST_ASSERT(n <= (std::numeric_limits<short>::max)());
  81. ast.tag(n);
  82. }
  83. else
  84. ast.tag(-1);
  85. }
  86. };
  87. template <typename Iterator, typename F>
  88. struct tagger : qi::grammar<Iterator, void(utree&, char)>
  89. {
  90. qi::rule<Iterator, void(utree&, char)>
  91. start;
  92. qi::rule<Iterator, void(utree&)>
  93. epsilon;
  94. px::function<F>
  95. f;
  96. tagger(F f_ = F()) : tagger::base_type(start), f(f_)
  97. {
  98. using qi::omit;
  99. using qi::raw;
  100. using qi::eps;
  101. using qi::lit;
  102. using qi::_1;
  103. using qi::_r1;
  104. using qi::_r2;
  105. start = omit[raw[lit(_r2)] [f(_r1, _1)]];
  106. epsilon = omit[raw[eps] [f(_r1, _1)]];
  107. }
  108. };
  109. template <typename Iterator>
  110. struct whitespace : qi::grammar<Iterator> {
  111. qi::rule<Iterator>
  112. start;
  113. whitespace() : whitespace::base_type(start)
  114. {
  115. using standard::space;
  116. using standard::char_;
  117. using qi::eol;
  118. start = space | (';' >> *(char_ - eol) >> eol);
  119. }
  120. };
  121. } // sexpr
  122. //[utree_sexpr_parser
  123. namespace sexpr
  124. {
  125. template <typename Iterator, typename ErrorHandler = error_handler<Iterator> >
  126. struct parser : qi::grammar<Iterator, utree(), whitespace<Iterator> >
  127. {
  128. qi::rule<Iterator, utree(), whitespace<Iterator> >
  129. start, element, list;
  130. qi::rule<Iterator, utree()>
  131. atom;
  132. qi::rule<Iterator, int()>
  133. integer;
  134. qi::rule<Iterator, utf8_symbol_type()>
  135. symbol;
  136. qi::rule<Iterator, utree::nil_type()>
  137. nil_;
  138. qi::rule<Iterator, binary_string_type()>
  139. binary;
  140. utf8::parser<Iterator>
  141. string;
  142. px::function<ErrorHandler> const
  143. error;
  144. tagger<Iterator, save_line_pos>
  145. pos;
  146. parser(std::string const& source_file = "<string>"):
  147. parser::base_type(start), error(ErrorHandler(source_file))
  148. {
  149. using standard::char_;
  150. using qi::unused_type;
  151. using qi::lexeme;
  152. using qi::hex;
  153. using qi::oct;
  154. using qi::no_case;
  155. using qi::real_parser;
  156. using qi::strict_real_policies;
  157. using qi::uint_parser;
  158. using qi::bool_parser;
  159. using qi::on_error;
  160. using qi::fail;
  161. using qi::int_;
  162. using qi::lit;
  163. using qi::_val;
  164. using qi::_1;
  165. using qi::_2;
  166. using qi::_3;
  167. using qi::_4;
  168. real_parser<double, strict_real_policies<double> > strict_double;
  169. uint_parser<unsigned char, 16, 2, 2> hex2;
  170. bool_parser<bool, sexpr::bool_input_policies> boolean;
  171. start = element.alias();
  172. element = atom | list;
  173. list = pos(_val, '(') > *element > ')';
  174. atom = nil_
  175. | strict_double
  176. | integer
  177. | boolean
  178. | string
  179. | symbol
  180. | binary;
  181. nil_ = qi::attr_cast(lit("nil"));
  182. integer = lexeme[ no_case["#x"] > hex]
  183. | lexeme[ no_case["#o"] >> oct]
  184. | lexeme[-no_case["#d"] >> int_];
  185. std::string exclude = std::string(" ();\"\x01-\x1f\x7f") + '\0';
  186. symbol = lexeme[+(~char_(exclude))];
  187. binary = lexeme['#' > *hex2 > '#'];
  188. start.name("sexpr");
  189. element.name("element");
  190. list.name("list");
  191. atom.name("atom");
  192. nil_.name("nil");
  193. integer.name("integer");
  194. symbol.name("symbol");
  195. binary.name("binary");
  196. on_error<fail>(start, error(_1, _2, _3, _4));
  197. }
  198. };
  199. } // sexpr
  200. //]
  201. #endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP