annotate DEPENDENCIES/generic/include/boost/spirit/home/classic/utility/confix.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 /*=============================================================================
Chris@16 2 Copyright (c) 2002-2003 Hartmut Kaiser
Chris@16 3 http://spirit.sourceforge.net/
Chris@16 4
Chris@16 5 Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@16 6 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7 =============================================================================*/
Chris@16 8 #ifndef BOOST_SPIRIT_CONFIX_HPP
Chris@16 9 #define BOOST_SPIRIT_CONFIX_HPP
Chris@16 10
Chris@16 11 ///////////////////////////////////////////////////////////////////////////////
Chris@16 12 #include <boost/config.hpp>
Chris@16 13 #include <boost/spirit/home/classic/namespace.hpp>
Chris@16 14 #include <boost/spirit/home/classic/meta/as_parser.hpp>
Chris@16 15 #include <boost/spirit/home/classic/core/composite/operators.hpp>
Chris@16 16
Chris@16 17 #include <boost/spirit/home/classic/utility/confix_fwd.hpp>
Chris@16 18 #include <boost/spirit/home/classic/utility/impl/confix.ipp>
Chris@16 19
Chris@16 20 ///////////////////////////////////////////////////////////////////////////////
Chris@16 21 namespace boost { namespace spirit {
Chris@16 22
Chris@16 23 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
Chris@16 24
Chris@16 25 ///////////////////////////////////////////////////////////////////////////////
Chris@16 26 //
Chris@16 27 // confix_parser class
Chris@16 28 //
Chris@16 29 // Parses a sequence of 3 sub-matches. This class may
Chris@16 30 // be used to parse structures, where the opening part is possibly
Chris@16 31 // contained in the expression part and the whole sequence is only
Chris@16 32 // parsed after seeing the closing part matching the first opening
Chris@16 33 // subsequence. Example: C-comments:
Chris@16 34 //
Chris@16 35 // /* This is a C-comment */
Chris@16 36 //
Chris@16 37 ///////////////////////////////////////////////////////////////////////////////
Chris@16 38
Chris@16 39 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
Chris@16 40 #pragma warning(push)
Chris@16 41 #pragma warning(disable:4512) //assignment operator could not be generated
Chris@16 42 #endif
Chris@16 43
Chris@16 44 template<typename NestedT = non_nested, typename LexemeT = non_lexeme>
Chris@16 45 struct confix_parser_gen;
Chris@16 46
Chris@16 47 template <
Chris@16 48 typename OpenT, typename ExprT, typename CloseT, typename CategoryT,
Chris@16 49 typename NestedT, typename LexemeT
Chris@16 50 >
Chris@16 51 struct confix_parser :
Chris@16 52 public parser<
Chris@16 53 confix_parser<OpenT, ExprT, CloseT, CategoryT, NestedT, LexemeT>
Chris@16 54 >
Chris@16 55 {
Chris@16 56 typedef
Chris@16 57 confix_parser<OpenT, ExprT, CloseT, CategoryT, NestedT, LexemeT>
Chris@16 58 self_t;
Chris@16 59
Chris@16 60 confix_parser(OpenT const &open_, ExprT const &expr_, CloseT const &close_)
Chris@16 61 : open(open_), expr(expr_), close(close_)
Chris@16 62 {}
Chris@16 63
Chris@16 64 template <typename ScannerT>
Chris@16 65 typename parser_result<self_t, ScannerT>::type
Chris@16 66 parse(ScannerT const& scan) const
Chris@16 67 {
Chris@16 68 return impl::confix_parser_type<CategoryT>::
Chris@16 69 parse(NestedT(), LexemeT(), *this, scan, open, expr, close);
Chris@16 70 }
Chris@16 71
Chris@16 72 private:
Chris@16 73
Chris@16 74 typename as_parser<OpenT>::type::embed_t open;
Chris@16 75 typename as_parser<ExprT>::type::embed_t expr;
Chris@16 76 typename as_parser<CloseT>::type::embed_t close;
Chris@16 77 };
Chris@16 78
Chris@16 79 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
Chris@16 80 #pragma warning(pop)
Chris@16 81 #endif
Chris@16 82
Chris@16 83 ///////////////////////////////////////////////////////////////////////////////
Chris@16 84 //
Chris@16 85 // Confix parser generator template
Chris@16 86 //
Chris@16 87 // This is a helper for generating a correct confix_parser<> from
Chris@16 88 // auxiliary parameters. There are the following types supported as
Chris@16 89 // parameters yet: parsers, single characters and strings (see
Chris@16 90 // as_parser).
Chris@16 91 //
Chris@16 92 // If the body parser is an action_parser_category type parser (a parser
Chris@16 93 // with an attached semantic action) we have to do something special. This
Chris@16 94 // happens, if the user wrote something like:
Chris@16 95 //
Chris@16 96 // confix_p(open, body[f], close)
Chris@16 97 //
Chris@16 98 // where 'body' is the parser matching the body of the confix sequence
Chris@16 99 // and 'f' is a functor to be called after matching the body. If we would
Chris@16 100 // do nothing, the resulting code would parse the sequence as follows:
Chris@16 101 //
Chris@16 102 // start >> (body[f] - close) >> close
Chris@16 103 //
Chris@16 104 // what in most cases is not what the user expects.
Chris@16 105 // (If this _is_ what you've expected, then please use the confix_p
Chris@16 106 // generator function 'direct()', which will inhibit
Chris@16 107 // re-attaching the actor to the body parser).
Chris@16 108 //
Chris@16 109 // To make the confix parser behave as expected:
Chris@16 110 //
Chris@16 111 // start >> (body - close)[f] >> close
Chris@16 112 //
Chris@16 113 // the actor attached to the 'body' parser has to be re-attached to the
Chris@16 114 // (body - close) parser construct, which will make the resulting confix
Chris@16 115 // parser 'do the right thing'. This refactoring is done by the help of
Chris@16 116 // the refactoring parsers (see the files refactoring.[hi]pp).
Chris@16 117 //
Chris@16 118 // Additionally special care must be taken, if the body parser is a
Chris@16 119 // unary_parser_category type parser as
Chris@16 120 //
Chris@16 121 // confix_p(open, *anychar_p, close)
Chris@16 122 //
Chris@16 123 // which without any refactoring would result in
Chris@16 124 //
Chris@16 125 // start >> (*anychar_p - close) >> close
Chris@16 126 //
Chris@16 127 // and will not give the expected result (*anychar_p will eat up all the
Chris@16 128 // input up to the end of the input stream). So we have to refactor this
Chris@16 129 // into:
Chris@16 130 //
Chris@16 131 // start >> *(anychar_p - close) >> close
Chris@16 132 //
Chris@16 133 // what will give the correct result.
Chris@16 134 //
Chris@16 135 // The case, where the body parser is a combination of the two mentioned
Chris@16 136 // problems (i.e. the body parser is a unary parser with an attached
Chris@16 137 // action), is handled accordingly too:
Chris@16 138 //
Chris@16 139 // confix_p(start, (*anychar_p)[f], end)
Chris@16 140 //
Chris@16 141 // will be parsed as expected:
Chris@16 142 //
Chris@16 143 // start >> (*(anychar_p - end))[f] >> end.
Chris@16 144 //
Chris@16 145 ///////////////////////////////////////////////////////////////////////////////
Chris@16 146
Chris@16 147 template<typename NestedT, typename LexemeT>
Chris@16 148 struct confix_parser_gen
Chris@16 149 {
Chris@16 150 // Generic generator function for creation of concrete confix parsers
Chris@16 151
Chris@16 152 template<typename StartT, typename ExprT, typename EndT>
Chris@16 153 struct paren_op_result_type
Chris@16 154 {
Chris@16 155 typedef confix_parser<
Chris@16 156 typename as_parser<StartT>::type,
Chris@16 157 typename as_parser<ExprT>::type,
Chris@16 158 typename as_parser<EndT>::type,
Chris@16 159 typename as_parser<ExprT>::type::parser_category_t,
Chris@16 160 NestedT,
Chris@16 161 LexemeT
Chris@16 162 > type;
Chris@16 163 };
Chris@16 164
Chris@16 165 template<typename StartT, typename ExprT, typename EndT>
Chris@16 166 typename paren_op_result_type<StartT, ExprT, EndT>::type
Chris@16 167 operator()(StartT const &start_, ExprT const &expr_, EndT const &end_) const
Chris@16 168 {
Chris@16 169 typedef typename paren_op_result_type<StartT,ExprT,EndT>::type
Chris@16 170 return_t;
Chris@16 171
Chris@16 172 return return_t(
Chris@16 173 as_parser<StartT>::convert(start_),
Chris@16 174 as_parser<ExprT>::convert(expr_),
Chris@16 175 as_parser<EndT>::convert(end_)
Chris@16 176 );
Chris@16 177 }
Chris@16 178
Chris@16 179 // Generic generator function for creation of concrete confix parsers
Chris@16 180 // which have an action directly attached to the ExprT part of the
Chris@16 181 // parser (see comment above, no automatic refactoring)
Chris@16 182
Chris@16 183 template<typename StartT, typename ExprT, typename EndT>
Chris@16 184 struct direct_result_type
Chris@16 185 {
Chris@16 186 typedef confix_parser<
Chris@16 187 typename as_parser<StartT>::type,
Chris@16 188 typename as_parser<ExprT>::type,
Chris@16 189 typename as_parser<EndT>::type,
Chris@16 190 plain_parser_category, // do not re-attach action
Chris@16 191 NestedT,
Chris@16 192 LexemeT
Chris@16 193 > type;
Chris@16 194 };
Chris@16 195
Chris@16 196 template<typename StartT, typename ExprT, typename EndT>
Chris@16 197 typename direct_result_type<StartT,ExprT,EndT>::type
Chris@16 198 direct(StartT const &start_, ExprT const &expr_, EndT const &end_) const
Chris@16 199 {
Chris@16 200 typedef typename direct_result_type<StartT,ExprT,EndT>::type
Chris@16 201 return_t;
Chris@16 202
Chris@16 203 return return_t(
Chris@16 204 as_parser<StartT>::convert(start_),
Chris@16 205 as_parser<ExprT>::convert(expr_),
Chris@16 206 as_parser<EndT>::convert(end_)
Chris@16 207 );
Chris@16 208 }
Chris@16 209 };
Chris@16 210
Chris@16 211 ///////////////////////////////////////////////////////////////////////////////
Chris@16 212 //
Chris@16 213 // Predefined non_nested confix parser generators
Chris@16 214 //
Chris@16 215 ///////////////////////////////////////////////////////////////////////////////
Chris@16 216
Chris@16 217 const confix_parser_gen<non_nested, non_lexeme> confix_p =
Chris@16 218 confix_parser_gen<non_nested, non_lexeme>();
Chris@16 219
Chris@16 220 ///////////////////////////////////////////////////////////////////////////////
Chris@16 221 //
Chris@16 222 // Comments are special types of confix parsers
Chris@16 223 //
Chris@16 224 // Comment parser generator template. This is a helper for generating a
Chris@16 225 // correct confix_parser<> from auxiliary parameters, which is able to
Chris@16 226 // parse comment constructs: (StartToken >> Comment text >> EndToken).
Chris@16 227 //
Chris@16 228 // There are the following types supported as parameters yet: parsers,
Chris@16 229 // single characters and strings (see as_parser).
Chris@16 230 //
Chris@16 231 // There are two diffenerent predefined comment parser generators
Chris@16 232 // (comment_p and comment_nest_p, see below), which may be used for
Chris@16 233 // creating special comment parsers in two different ways.
Chris@16 234 //
Chris@16 235 // If these are used with one parameter, a comment starting with the given
Chris@16 236 // first parser parameter up to the end of the line is matched. So for
Chris@16 237 // instance the following parser matches C++ style comments:
Chris@16 238 //
Chris@16 239 // comment_p("//").
Chris@16 240 //
Chris@16 241 // If these are used with two parameters, a comment starting with the
Chris@16 242 // first parser parameter up to the second parser parameter is matched.
Chris@16 243 // For instance a C style comment parser should be constrcuted as:
Chris@16 244 //
Chris@16 245 // comment_p("/*", "*/").
Chris@16 246 //
Chris@16 247 // Please note, that a comment is parsed implicitly as if the whole
Chris@16 248 // comment_p(...) statement were embedded into a lexeme_d[] directive.
Chris@16 249 //
Chris@16 250 ///////////////////////////////////////////////////////////////////////////////
Chris@16 251
Chris@16 252 template<typename NestedT>
Chris@16 253 struct comment_parser_gen
Chris@16 254 {
Chris@16 255 // Generic generator function for creation of concrete comment parsers
Chris@16 256 // from an open token. The newline parser eol_p is used as the
Chris@16 257 // closing token.
Chris@16 258
Chris@16 259 template<typename StartT>
Chris@16 260 struct paren_op1_result_type
Chris@16 261 {
Chris@16 262 typedef confix_parser<
Chris@16 263 typename as_parser<StartT>::type,
Chris@16 264 kleene_star<anychar_parser>,
Chris@16 265 alternative<eol_parser, end_parser>,
Chris@16 266 unary_parser_category, // there is no action to re-attach
Chris@16 267 NestedT,
Chris@16 268 is_lexeme // insert implicit lexeme_d[]
Chris@16 269 >
Chris@16 270 type;
Chris@16 271 };
Chris@16 272
Chris@16 273 template<typename StartT>
Chris@16 274 typename paren_op1_result_type<StartT>::type
Chris@16 275 operator() (StartT const &start_) const
Chris@16 276 {
Chris@16 277 typedef typename paren_op1_result_type<StartT>::type
Chris@16 278 return_t;
Chris@16 279
Chris@16 280 return return_t(
Chris@16 281 as_parser<StartT>::convert(start_),
Chris@16 282 *anychar_p,
Chris@16 283 eol_p | end_p
Chris@16 284 );
Chris@16 285 }
Chris@16 286
Chris@16 287 // Generic generator function for creation of concrete comment parsers
Chris@16 288 // from an open and a close tokens.
Chris@16 289
Chris@16 290 template<typename StartT, typename EndT>
Chris@16 291 struct paren_op2_result_type
Chris@16 292 {
Chris@16 293 typedef confix_parser<
Chris@16 294 typename as_parser<StartT>::type,
Chris@16 295 kleene_star<anychar_parser>,
Chris@16 296 typename as_parser<EndT>::type,
Chris@16 297 unary_parser_category, // there is no action to re-attach
Chris@16 298 NestedT,
Chris@16 299 is_lexeme // insert implicit lexeme_d[]
Chris@16 300 > type;
Chris@16 301 };
Chris@16 302
Chris@16 303 template<typename StartT, typename EndT>
Chris@16 304 typename paren_op2_result_type<StartT,EndT>::type
Chris@16 305 operator() (StartT const &start_, EndT const &end_) const
Chris@16 306 {
Chris@16 307 typedef typename paren_op2_result_type<StartT,EndT>::type
Chris@16 308 return_t;
Chris@16 309
Chris@16 310 return return_t(
Chris@16 311 as_parser<StartT>::convert(start_),
Chris@16 312 *anychar_p,
Chris@16 313 as_parser<EndT>::convert(end_)
Chris@16 314 );
Chris@16 315 }
Chris@16 316 };
Chris@16 317
Chris@16 318 ///////////////////////////////////////////////////////////////////////////////
Chris@16 319 //
Chris@16 320 // Predefined non_nested comment parser generator
Chris@16 321 //
Chris@16 322 ///////////////////////////////////////////////////////////////////////////////
Chris@16 323
Chris@16 324 const comment_parser_gen<non_nested> comment_p =
Chris@16 325 comment_parser_gen<non_nested>();
Chris@16 326
Chris@16 327 ///////////////////////////////////////////////////////////////////////////////
Chris@16 328 //
Chris@16 329 // comment_nest_parser class
Chris@16 330 //
Chris@16 331 // Parses a nested comments.
Chris@16 332 // Example: nested PASCAL-comments:
Chris@16 333 //
Chris@16 334 // { This is a { nested } PASCAL-comment }
Chris@16 335 //
Chris@16 336 ///////////////////////////////////////////////////////////////////////////////
Chris@16 337
Chris@16 338 template<typename OpenT, typename CloseT>
Chris@16 339 struct comment_nest_parser:
Chris@16 340 public parser<comment_nest_parser<OpenT, CloseT> >
Chris@16 341 {
Chris@16 342 typedef comment_nest_parser<OpenT, CloseT> self_t;
Chris@16 343
Chris@16 344 comment_nest_parser(OpenT const &open_, CloseT const &close_):
Chris@16 345 open(open_), close(close_)
Chris@16 346 {}
Chris@16 347
Chris@16 348 template<typename ScannerT>
Chris@16 349 typename parser_result<self_t, ScannerT>::type
Chris@16 350 parse(ScannerT const &scan) const
Chris@16 351 {
Chris@16 352 return do_parse(
Chris@16 353 open >> *(*this | (anychar_p - close)) >> close,
Chris@16 354 scan);
Chris@16 355 }
Chris@16 356
Chris@16 357 private:
Chris@16 358 template<typename ParserT, typename ScannerT>
Chris@16 359 typename parser_result<self_t, ScannerT>::type
Chris@16 360 do_parse(ParserT const &p, ScannerT const &scan) const
Chris@16 361 {
Chris@16 362 return
Chris@16 363 impl::contiguous_parser_parse<
Chris@16 364 typename parser_result<ParserT, ScannerT>::type
Chris@16 365 >(p, scan, scan);
Chris@16 366 }
Chris@16 367
Chris@16 368 typename as_parser<OpenT>::type::embed_t open;
Chris@16 369 typename as_parser<CloseT>::type::embed_t close;
Chris@16 370 };
Chris@16 371
Chris@16 372 ///////////////////////////////////////////////////////////////////////////////
Chris@16 373 //
Chris@16 374 // Predefined nested comment parser generator
Chris@16 375 //
Chris@16 376 ///////////////////////////////////////////////////////////////////////////////
Chris@16 377
Chris@16 378 template<typename OpenT, typename CloseT>
Chris@16 379 struct comment_nest_p_result
Chris@16 380 {
Chris@16 381 typedef comment_nest_parser<
Chris@16 382 typename as_parser<OpenT>::type,
Chris@16 383 typename as_parser<CloseT>::type
Chris@16 384 > type;
Chris@16 385 };
Chris@16 386
Chris@16 387 template<typename OpenT, typename CloseT>
Chris@16 388 inline typename comment_nest_p_result<OpenT,CloseT>::type
Chris@16 389 comment_nest_p(OpenT const &open, CloseT const &close)
Chris@16 390 {
Chris@16 391 typedef typename comment_nest_p_result<OpenT,CloseT>::type
Chris@16 392 result_t;
Chris@16 393
Chris@16 394 return result_t(
Chris@16 395 as_parser<OpenT>::convert(open),
Chris@16 396 as_parser<CloseT>::convert(close)
Chris@16 397 );
Chris@16 398 }
Chris@16 399
Chris@16 400 ///////////////////////////////////////////////////////////////////////////////
Chris@16 401 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
Chris@16 402
Chris@16 403 }} // namespace BOOST_SPIRIT_CLASSIC_NS
Chris@16 404
Chris@16 405 #endif