annotate DEPENDENCIES/generic/include/boost/spirit/home/lex/tokenize_and_parse.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // Copyright (c) 2001-2011 Hartmut Kaiser
Chris@16 2 //
Chris@16 3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 5
Chris@16 6 #if !defined(BOOST_SPIRIT_LEXER_PARSE_NOV_17_2007_0246PM)
Chris@16 7 #define BOOST_SPIRIT_LEXER_PARSE_NOV_17_2007_0246PM
Chris@16 8
Chris@16 9 #if defined(_MSC_VER)
Chris@16 10 #pragma once
Chris@16 11 #endif
Chris@16 12
Chris@16 13 #include <boost/spirit/home/qi/skip_over.hpp>
Chris@16 14 #include <boost/spirit/home/qi/parse.hpp>
Chris@16 15 #include <boost/spirit/home/qi/nonterminal/grammar.hpp>
Chris@16 16 #include <boost/spirit/home/support/unused.hpp>
Chris@16 17 #include <boost/spirit/home/lex/lexer.hpp>
Chris@16 18 #include <boost/mpl/assert.hpp>
Chris@16 19
Chris@16 20 namespace boost { namespace spirit { namespace lex
Chris@16 21 {
Chris@16 22 ///////////////////////////////////////////////////////////////////////////
Chris@16 23 // Import skip_flag enumerator type from Qi namespace
Chris@16 24 using qi::skip_flag;
Chris@16 25
Chris@16 26 ///////////////////////////////////////////////////////////////////////////
Chris@16 27 //
Chris@16 28 // The tokenize_and_parse() function is one of the main Spirit API
Chris@16 29 // functions. It simplifies using a lexer as the underlying token source
Chris@16 30 // while parsing a given input sequence.
Chris@16 31 //
Chris@16 32 // The function takes a pair of iterators spanning the underlying input
Chris@16 33 // stream to parse, the lexer object (built from the token definitions)
Chris@16 34 // and a parser object (built from the parser grammar definition).
Chris@16 35 //
Chris@16 36 // The second version of this function additionally takes an attribute to
Chris@16 37 // be used as the top level data structure instance the parser should use
Chris@16 38 // to store the recognized input to.
Chris@16 39 //
Chris@16 40 // The function returns true if the parsing succeeded (the given input
Chris@16 41 // sequence has been successfully matched by the given grammar).
Chris@16 42 //
Chris@16 43 // first, last: The pair of iterators spanning the underlying input
Chris@16 44 // sequence to parse. These iterators must at least
Chris@16 45 // conform to the requirements of the std::intput_iterator
Chris@16 46 // category.
Chris@16 47 // On exit the iterator 'first' will be updated to the
Chris@16 48 // position right after the last successfully matched
Chris@16 49 // token.
Chris@16 50 // lex: The lexer object (encoding the token definitions) to be
Chris@16 51 // used to convert the input sequence into a sequence of
Chris@16 52 // tokens. This token sequence is passed to the parsing
Chris@16 53 // process. The LexerExpr type must conform to the
Chris@16 54 // lexer interface described in the corresponding section
Chris@16 55 // of the documentation.
Chris@16 56 // xpr: The grammar object (encoding the parser grammar) to be
Chris@16 57 // used to match the token sequence generated by the lex
Chris@16 58 // object instance. The ParserExpr type must conform to
Chris@16 59 // the grammar interface described in the corresponding
Chris@16 60 // section of the documentation.
Chris@16 61 // attr: The top level attribute passed to the parser. It will
Chris@16 62 // be populated during the parsing of the input sequence.
Chris@16 63 // On exit it will hold the 'parser result' corresponding
Chris@16 64 // to the matched input sequence.
Chris@16 65 //
Chris@16 66 ///////////////////////////////////////////////////////////////////////////
Chris@16 67 template <typename Iterator, typename Lexer, typename ParserExpr>
Chris@16 68 inline bool
Chris@16 69 tokenize_and_parse(Iterator& first, Iterator last, Lexer const& lex,
Chris@16 70 ParserExpr const& xpr)
Chris@16 71 {
Chris@16 72 // Report invalid expression error as early as possible.
Chris@16 73 // If you got an error_invalid_expression error message here,
Chris@16 74 // then the expression (expr) is not a valid spirit qi expression.
Chris@16 75 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
Chris@16 76
Chris@16 77 typename Lexer::iterator_type iter = lex.begin(first, last);
Chris@16 78 return compile<qi::domain>(xpr).parse(
Chris@16 79 iter, lex.end(), unused, unused, unused);
Chris@16 80 }
Chris@16 81
Chris@16 82 ///////////////////////////////////////////////////////////////////////////
Chris@16 83 template <typename Iterator, typename Lexer, typename ParserExpr
Chris@16 84 , typename Attribute>
Chris@16 85 inline bool
Chris@16 86 tokenize_and_parse(Iterator& first, Iterator last, Lexer const& lex
Chris@16 87 , ParserExpr const& xpr, Attribute& attr)
Chris@16 88 {
Chris@16 89 // Report invalid expression error as early as possible.
Chris@16 90 // If you got an error_invalid_expression error message here,
Chris@16 91 // then the expression (expr) is not a valid spirit qi expression.
Chris@16 92 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
Chris@16 93
Chris@16 94 typename Lexer::iterator_type iter = lex.begin(first, last);
Chris@16 95 return compile<qi::domain>(xpr).parse(
Chris@16 96 iter, lex.end(), unused, unused, attr);
Chris@16 97 }
Chris@16 98
Chris@16 99 ///////////////////////////////////////////////////////////////////////////
Chris@16 100 //
Chris@16 101 // The tokenize_and_phrase_parse() function is one of the main Spirit API
Chris@16 102 // functions. It simplifies using a lexer as the underlying token source
Chris@16 103 // while phrase parsing a given input sequence.
Chris@16 104 //
Chris@16 105 // The function takes a pair of iterators spanning the underlying input
Chris@16 106 // stream to parse, the lexer object (built from the token definitions)
Chris@16 107 // and a parser object (built from the parser grammar definition). The
Chris@16 108 // additional skipper parameter will be used as the skip parser during
Chris@16 109 // the parsing process.
Chris@16 110 //
Chris@16 111 // The second version of this function additionally takes an attribute to
Chris@16 112 // be used as the top level data structure instance the parser should use
Chris@16 113 // to store the recognized input to.
Chris@16 114 //
Chris@16 115 // The function returns true if the parsing succeeded (the given input
Chris@16 116 // sequence has been successfully matched by the given grammar).
Chris@16 117 //
Chris@16 118 // first, last: The pair of iterators spanning the underlying input
Chris@16 119 // sequence to parse. These iterators must at least
Chris@16 120 // conform to the requirements of the std::intput_iterator
Chris@16 121 // category.
Chris@16 122 // On exit the iterator 'first' will be updated to the
Chris@16 123 // position right after the last successfully matched
Chris@16 124 // token.
Chris@16 125 // lex: The lexer object (encoding the token definitions) to be
Chris@16 126 // used to convert the input sequence into a sequence of
Chris@16 127 // tokens. This token sequence is passed to the parsing
Chris@16 128 // process. The LexerExpr type must conform to the
Chris@16 129 // lexer interface described in the corresponding section
Chris@16 130 // of the documentation.
Chris@16 131 // xpr: The grammar object (encoding the parser grammar) to be
Chris@16 132 // used to match the token sequence generated by the lex
Chris@16 133 // object instance. The ParserExpr type must conform to
Chris@16 134 // the grammar interface described in the corresponding
Chris@16 135 // section of the documentation.
Chris@16 136 // skipper: The skip parser to be used while parsing the given
Chris@16 137 // input sequence. Note, the skip parser will have to
Chris@16 138 // act on the same token sequence as the main parser
Chris@16 139 // 'xpr'.
Chris@16 140 // post_skip: The post_skip flag controls whether the function will
Chris@16 141 // invoke an additional post skip after the main parser
Chris@16 142 // returned.
Chris@16 143 // attr: The top level attribute passed to the parser. It will
Chris@16 144 // be populated during the parsing of the input sequence.
Chris@16 145 // On exit it will hold the 'parser result' corresponding
Chris@16 146 // to the matched input sequence.
Chris@16 147 //
Chris@16 148 ///////////////////////////////////////////////////////////////////////////
Chris@16 149 template <typename Iterator, typename Lexer, typename ParserExpr
Chris@16 150 , typename Skipper>
Chris@16 151 inline bool
Chris@16 152 tokenize_and_phrase_parse(Iterator& first, Iterator last
Chris@16 153 , Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
Chris@16 154 , BOOST_SCOPED_ENUM(skip_flag) post_skip = skip_flag::postskip)
Chris@16 155 {
Chris@16 156 // Report invalid expression error as early as possible.
Chris@16 157 // If you got an error_invalid_expression error message here,
Chris@16 158 // then the expression (expr) is not a valid spirit qi expression.
Chris@16 159 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
Chris@16 160 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
Chris@16 161
Chris@16 162 typedef
Chris@16 163 typename spirit::result_of::compile<qi::domain, Skipper>::type
Chris@16 164 skipper_type;
Chris@16 165 skipper_type const skipper_ = compile<qi::domain>(skipper);
Chris@16 166
Chris@16 167 typename Lexer::iterator_type iter = lex.begin(first, last);
Chris@16 168 typename Lexer::iterator_type end = lex.end();
Chris@16 169 if (!compile<qi::domain>(xpr).parse(
Chris@16 170 iter, end, unused, skipper_, unused))
Chris@16 171 return false;
Chris@16 172
Chris@16 173 // do a final post-skip
Chris@16 174 if (post_skip == skip_flag::postskip)
Chris@16 175 qi::skip_over(iter, end, skipper_);
Chris@16 176 return true;
Chris@16 177 }
Chris@16 178
Chris@16 179 template <typename Iterator, typename Lexer, typename ParserExpr
Chris@16 180 , typename Skipper, typename Attribute>
Chris@16 181 inline bool
Chris@16 182 tokenize_and_phrase_parse(Iterator& first, Iterator last
Chris@16 183 , Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
Chris@16 184 , BOOST_SCOPED_ENUM(skip_flag) post_skip, Attribute& attr)
Chris@16 185 {
Chris@16 186 // Report invalid expression error as early as possible.
Chris@16 187 // If you got an error_invalid_expression error message here,
Chris@16 188 // then the expression (expr) is not a valid spirit qi expression.
Chris@16 189 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
Chris@16 190 BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
Chris@16 191
Chris@16 192 typedef
Chris@16 193 typename spirit::result_of::compile<qi::domain, Skipper>::type
Chris@16 194 skipper_type;
Chris@16 195 skipper_type const skipper_ = compile<qi::domain>(skipper);
Chris@16 196
Chris@16 197 typename Lexer::iterator_type iter = lex.begin(first, last);
Chris@16 198 typename Lexer::iterator_type end = lex.end();
Chris@16 199 if (!compile<qi::domain>(xpr).parse(
Chris@16 200 iter, end, unused, skipper_, attr))
Chris@16 201 return false;
Chris@16 202
Chris@16 203 // do a final post-skip
Chris@16 204 if (post_skip == skip_flag::postskip)
Chris@16 205 qi::skip_over(iter, end, skipper_);
Chris@16 206 return true;
Chris@16 207 }
Chris@16 208
Chris@16 209 ///////////////////////////////////////////////////////////////////////////
Chris@16 210 template <typename Iterator, typename Lexer, typename ParserExpr
Chris@16 211 , typename Skipper, typename Attribute>
Chris@16 212 inline bool
Chris@16 213 tokenize_and_phrase_parse(Iterator& first, Iterator last
Chris@16 214 , Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
Chris@16 215 , Attribute& attr)
Chris@16 216 {
Chris@16 217 return tokenize_and_phrase_parse(first, last, lex, xpr, skipper
Chris@16 218 , skip_flag::postskip, attr);
Chris@16 219 }
Chris@16 220
Chris@16 221 ///////////////////////////////////////////////////////////////////////////
Chris@16 222 //
Chris@16 223 // The tokenize() function is one of the main Spirit API functions. It
Chris@16 224 // simplifies using a lexer to tokenize a given input sequence. It's main
Chris@16 225 // purpose is to use the lexer to tokenize all the input.
Chris@16 226 //
Chris@16 227 // The second version below discards all generated tokens afterwards.
Chris@16 228 // This is useful whenever all the needed functionality has been
Chris@16 229 // implemented directly inside the lexer semantic actions, which are being
Chris@16 230 // executed while the tokens are matched.
Chris@16 231 //
Chris@16 232 // The function takes a pair of iterators spanning the underlying input
Chris@16 233 // stream to scan, the lexer object (built from the token definitions),
Chris@16 234 // and a (optional) functor being called for each of the generated tokens.
Chris@16 235 //
Chris@16 236 // The function returns true if the scanning of the input succeeded (the
Chris@16 237 // given input sequence has been successfully matched by the given token
Chris@16 238 // definitions).
Chris@16 239 //
Chris@16 240 // first, last: The pair of iterators spanning the underlying input
Chris@16 241 // sequence to parse. These iterators must at least
Chris@16 242 // conform to the requirements of the std::intput_iterator
Chris@16 243 // category.
Chris@16 244 // On exit the iterator 'first' will be updated to the
Chris@16 245 // position right after the last successfully matched
Chris@16 246 // token.
Chris@16 247 // lex: The lexer object (encoding the token definitions) to be
Chris@16 248 // used to convert the input sequence into a sequence of
Chris@16 249 // tokens. The LexerExpr type must conform to the
Chris@16 250 // lexer interface described in the corresponding section
Chris@16 251 // of the documentation.
Chris@16 252 // f: A functor (callable object) taking a single argument of
Chris@16 253 // the token type and returning a bool, indicating whether
Chris@16 254 // the tokenization should be canceled.
Chris@16 255 // initial_state: The name of the state the lexer should start matching.
Chris@16 256 // The default value is zero, causing the lexer to start
Chris@16 257 // in its 'INITIAL' state.
Chris@16 258 //
Chris@16 259 ///////////////////////////////////////////////////////////////////////////
Chris@16 260 namespace detail
Chris@16 261 {
Chris@16 262 template <typename Token, typename F>
Chris@16 263 bool tokenize_callback(Token const& t, F f)
Chris@16 264 {
Chris@16 265 return f(t);
Chris@16 266 }
Chris@16 267
Chris@16 268 template <typename Token, typename Eval>
Chris@16 269 bool tokenize_callback(Token const& t, phoenix::actor<Eval> const& f)
Chris@16 270 {
Chris@16 271 f(t);
Chris@16 272 return true;
Chris@16 273 }
Chris@16 274
Chris@16 275 template <typename Token>
Chris@16 276 bool tokenize_callback(Token const& t, void (*f)(Token const&))
Chris@16 277 {
Chris@16 278 f(t);
Chris@16 279 return true;
Chris@16 280 }
Chris@16 281
Chris@16 282 template <typename Token>
Chris@16 283 bool tokenize_callback(Token const& t, bool (*f)(Token const&))
Chris@16 284 {
Chris@16 285 return f(t);
Chris@16 286 }
Chris@16 287 }
Chris@16 288
Chris@16 289 template <typename Iterator, typename Lexer, typename F>
Chris@16 290 inline bool
Chris@16 291 tokenize(Iterator& first, Iterator last, Lexer const& lex, F f
Chris@16 292 , typename Lexer::char_type const* initial_state = 0)
Chris@16 293 {
Chris@16 294 typedef typename Lexer::iterator_type iterator_type;
Chris@16 295
Chris@16 296 iterator_type iter = lex.begin(first, last, initial_state);
Chris@16 297 iterator_type end = lex.end();
Chris@16 298 for (/**/; iter != end && token_is_valid(*iter); ++iter)
Chris@16 299 {
Chris@16 300 if (!detail::tokenize_callback(*iter, f))
Chris@16 301 return false;
Chris@16 302 }
Chris@16 303 return (iter == end) ? true : false;
Chris@16 304 }
Chris@16 305
Chris@16 306 ///////////////////////////////////////////////////////////////////////////
Chris@16 307 template <typename Iterator, typename Lexer>
Chris@16 308 inline bool
Chris@16 309 tokenize(Iterator& first, Iterator last, Lexer const& lex
Chris@16 310 , typename Lexer::char_type const* initial_state = 0)
Chris@16 311 {
Chris@16 312 typedef typename Lexer::iterator_type iterator_type;
Chris@16 313
Chris@16 314 iterator_type iter = lex.begin(first, last, initial_state);
Chris@16 315 iterator_type end = lex.end();
Chris@16 316
Chris@16 317 while (iter != end && token_is_valid(*iter))
Chris@16 318 ++iter;
Chris@16 319
Chris@16 320 return (iter == end) ? true : false;
Chris@16 321 }
Chris@16 322
Chris@16 323 }}}
Chris@16 324
Chris@16 325 #endif