/////////////////////////////////////////////////////////////////////////////// /// \file regex_primitives.hpp /// Contains the syntax elements for writing static regular expressions. // // Copyright 2008 Eric Niebler. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_XPRESSIVE_REGEX_PRIMITIVES_HPP_EAN_10_04_2005 #define BOOST_XPRESSIVE_REGEX_PRIMITIVES_HPP_EAN_10_04_2005 #include #include #include #include #include #include #include #include #include #include #include #include #include // Doxygen can't handle proto :-( #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED # include # include # include # include # include # include #endif namespace boost { namespace xpressive { namespace detail { typedef assert_word_placeholder > assert_word_boundary; typedef assert_word_placeholder assert_word_begin; typedef assert_word_placeholder assert_word_end; // workaround msvc-7.1 bug with function pointer types // within function types: #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) #define mark_number(x) proto::call #define minus_one() proto::make #endif struct push_back : proto::callable { typedef int result_type; template int operator ()(Subs &subs, int i) const { subs.push_back(i); return i; } }; struct mark_number : proto::callable { typedef int result_type; template int operator ()(Expr const &expr) const { return expr.mark_number_; } }; typedef mpl::int_<-1> minus_one; // s1 or -s1 struct SubMatch : proto::or_< proto::when , proto::when, push_back(proto::_data, minus_one()) > > {}; struct SubMatchList : proto::or_ > {}; template typename enable_if< mpl::and_, proto::matches > , std::vector >::type to_vector(Subs const &subs) { std::vector subs_; SubMatchList()(subs, 0, subs_); return subs_; } #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) #undef mark_number #undef minus_one #endif // replace "Expr" with "keep(*State) >> Expr" struct skip_primitives : proto::transform { template struct impl : proto::transform_impl { typedef typename proto::shift_right< typename proto::unary_expr< keeper_tag , typename proto::dereference::type >::type , Expr >::type result_type; result_type operator ()( typename impl::expr_param expr , typename impl::state_param state , typename impl::data_param ) const { result_type that = {{{state}}, expr}; return that; } }; }; struct Primitives : proto::or_< proto::terminal , proto::comma , proto::subscript, proto::_> , proto::assign, proto::_> , proto::assign >, proto::_> , proto::complement > {}; struct SkipGrammar : proto::or_< proto::when , proto::assign, SkipGrammar> // don't "skip" mark tags , proto::subscript // don't put skips in actions , proto::binary_expr // don't skip modifiers , proto::unary_expr // don't skip lookbehinds , proto::nary_expr > // everything else is fair game! > {}; template struct skip_directive { typedef typename proto::result_of::as_expr::type skip_type; skip_directive(Skip const &skip) : skip_(proto::as_expr(skip)) {} template struct result {}; template struct result { typedef SkipGrammar::impl< typename proto::result_of::as_expr::type , skip_type const & , mpl::void_ & > skip_transform; typedef typename proto::shift_right< typename skip_transform::result_type , typename proto::dereference::type >::type type; }; template typename result::type operator ()(Expr const &expr) const { mpl::void_ ignore; typedef result result_fun; typename result_fun::type that = { typename result_fun::skip_transform()(proto::as_expr(expr), this->skip_, ignore) , {skip_} }; return that; } private: skip_type skip_; }; /* /////////////////////////////////////////////////////////////////////////////// /// INTERNAL ONLY // BOOST_XPRESSIVE_GLOBAL // for defining globals that neither violate the One Definition Rule nor // lead to undefined behavior due to global object initialization order. //#define BOOST_XPRESSIVE_GLOBAL(type, name, init) \ // namespace detail \ // { \ // template \ // struct BOOST_PP_CAT(global_pod_, name) \ // { \ // static type const value; \ // private: \ // union type_must_be_pod \ // { \ // type t; \ // char ch; \ // } u; \ // }; \ // template \ // type const BOOST_PP_CAT(global_pod_, name)::value = init; \ // } \ // type const &name = detail::BOOST_PP_CAT(global_pod_, name)<0>::value */ } // namespace detail /// INTERNAL ONLY (for backwards compatibility) unsigned int const repeat_max = UINT_MAX-1; /////////////////////////////////////////////////////////////////////////////// /// \brief For infinite repetition of a sub-expression. /// /// Magic value used with the repeat\<\>() function template /// to specify an unbounded repeat. Use as: repeat<17, inf>('a'). /// The equivalent in perl is /a{17,}/. unsigned int const inf = UINT_MAX-1; /// INTERNAL ONLY (for backwards compatibility) proto::terminal::type const epsilon = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Successfully matches nothing. /// /// Successfully matches a zero-width sequence. nil always succeeds and /// never consumes any characters. proto::terminal::type const nil = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches an alpha-numeric character. /// /// The regex traits are used to determine which characters are alpha-numeric. /// To match any character that is not alpha-numeric, use ~alnum. /// /// \attention alnum is equivalent to /[[:alnum:]]/ in perl. ~alnum is equivalent /// to /[[:^alnum:]]/ in perl. proto::terminal::type const alnum = {{"alnum", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches an alphabetic character. /// /// The regex traits are used to determine which characters are alphabetic. /// To match any character that is not alphabetic, use ~alpha. /// /// \attention alpha is equivalent to /[[:alpha:]]/ in perl. ~alpha is equivalent /// to /[[:^alpha:]]/ in perl. proto::terminal::type const alpha = {{"alpha", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a blank (horizonal white-space) character. /// /// The regex traits are used to determine which characters are blank characters. /// To match any character that is not blank, use ~blank. /// /// \attention blank is equivalent to /[[:blank:]]/ in perl. ~blank is equivalent /// to /[[:^blank:]]/ in perl. proto::terminal::type const blank = {{"blank", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a control character. /// /// The regex traits are used to determine which characters are control characters. /// To match any character that is not a control character, use ~cntrl. /// /// \attention cntrl is equivalent to /[[:cntrl:]]/ in perl. ~cntrl is equivalent /// to /[[:^cntrl:]]/ in perl. proto::terminal::type const cntrl = {{"cntrl", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a digit character. /// /// The regex traits are used to determine which characters are digits. /// To match any character that is not a digit, use ~digit. /// /// \attention digit is equivalent to /[[:digit:]]/ in perl. ~digit is equivalent /// to /[[:^digit:]]/ in perl. proto::terminal::type const digit = {{"digit", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a graph character. /// /// The regex traits are used to determine which characters are graphable. /// To match any character that is not graphable, use ~graph. /// /// \attention graph is equivalent to /[[:graph:]]/ in perl. ~graph is equivalent /// to /[[:^graph:]]/ in perl. proto::terminal::type const graph = {{"graph", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a lower-case character. /// /// The regex traits are used to determine which characters are lower-case. /// To match any character that is not a lower-case character, use ~lower. /// /// \attention lower is equivalent to /[[:lower:]]/ in perl. ~lower is equivalent /// to /[[:^lower:]]/ in perl. proto::terminal::type const lower = {{"lower", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a printable character. /// /// The regex traits are used to determine which characters are printable. /// To match any character that is not printable, use ~print. /// /// \attention print is equivalent to /[[:print:]]/ in perl. ~print is equivalent /// to /[[:^print:]]/ in perl. proto::terminal::type const print = {{"print", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a punctuation character. /// /// The regex traits are used to determine which characters are punctuation. /// To match any character that is not punctuation, use ~punct. /// /// \attention punct is equivalent to /[[:punct:]]/ in perl. ~punct is equivalent /// to /[[:^punct:]]/ in perl. proto::terminal::type const punct = {{"punct", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a space character. /// /// The regex traits are used to determine which characters are space characters. /// To match any character that is not white-space, use ~space. /// /// \attention space is equivalent to /[[:space:]]/ in perl. ~space is equivalent /// to /[[:^space:]]/ in perl. proto::terminal::type const space = {{"space", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches an upper-case character. /// /// The regex traits are used to determine which characters are upper-case. /// To match any character that is not upper-case, use ~upper. /// /// \attention upper is equivalent to /[[:upper:]]/ in perl. ~upper is equivalent /// to /[[:^upper:]]/ in perl. proto::terminal::type const upper = {{"upper", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a hexadecimal digit character. /// /// The regex traits are used to determine which characters are hex digits. /// To match any character that is not a hex digit, use ~xdigit. /// /// \attention xdigit is equivalent to /[[:xdigit:]]/ in perl. ~xdigit is equivalent /// to /[[:^xdigit:]]/ in perl. proto::terminal::type const xdigit = {{"xdigit", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Beginning of sequence assertion. /// /// For the character sequence [begin, end), 'bos' matches the /// zero-width sub-sequence [begin, begin). proto::terminal::type const bos = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief End of sequence assertion. /// /// For the character sequence [begin, end), /// 'eos' matches the zero-width sub-sequence [end, end). /// /// \attention Unlike the perl end of sequence assertion \$, 'eos' will /// not match at the position [end-1, end-1) if *(end-1) is '\\n'. To /// get that behavior, use (!_n >> eos). proto::terminal::type const eos = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Beginning of line assertion. /// /// 'bol' matches the zero-width sub-sequence /// immediately following a logical newline sequence. The regex traits /// is used to determine what constitutes a logical newline sequence. proto::terminal::type const bol = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief End of line assertion. /// /// 'eol' matches the zero-width sub-sequence /// immediately preceeding a logical newline sequence. The regex traits /// is used to determine what constitutes a logical newline sequence. proto::terminal::type const eol = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Beginning of word assertion. /// /// 'bow' matches the zero-width sub-sequence /// immediately following a non-word character and preceeding a word character. /// The regex traits are used to determine what constitutes a word character. proto::terminal::type const bow = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief End of word assertion. /// /// 'eow' matches the zero-width sub-sequence /// immediately following a word character and preceeding a non-word character. /// The regex traits are used to determine what constitutes a word character. proto::terminal::type const eow = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Word boundary assertion. /// /// '_b' matches the zero-width sub-sequence at the beginning or the end of a word. /// It is equivalent to (bow | eow). The regex traits are used to determine what /// constitutes a word character. To match a non-word boundary, use ~_b. /// /// \attention _b is like \\b in perl. ~_b is like \\B in perl. proto::terminal::type const _b = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a word character. /// /// '_w' matches a single word character. The regex traits are used to determine which /// characters are word characters. Use ~_w to match a character that is not a word /// character. /// /// \attention _w is like \\w in perl. ~_w is like \\W in perl. proto::terminal::type const _w = {{"w", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a digit character. /// /// '_d' matches a single digit character. The regex traits are used to determine which /// characters are digits. Use ~_d to match a character that is not a digit /// character. /// /// \attention _d is like \\d in perl. ~_d is like \\D in perl. proto::terminal::type const _d = {{"d", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a space character. /// /// '_s' matches a single space character. The regex traits are used to determine which /// characters are space characters. Use ~_s to match a character that is not a space /// character. /// /// \attention _s is like \\s in perl. ~_s is like \\S in perl. proto::terminal::type const _s = {{"s", false}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a literal newline character, '\\n'. /// /// '_n' matches a single newline character, '\\n'. Use ~_n to match a character /// that is not a newline. /// /// \attention ~_n is like '.' in perl without the /s modifier. proto::terminal::type const _n = {'\n'}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches a logical newline sequence. /// /// '_ln' matches a logical newline sequence. This can be any character in the /// line separator class, as determined by the regex traits, or the '\\r\\n' sequence. /// For the purpose of back-tracking, '\\r\\n' is treated as a unit. /// To match any one character that is not a logical newline, use ~_ln. detail::logical_newline_xpression const _ln = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Matches any one character. /// /// Match any character, similar to '.' in perl syntax with the /s modifier. /// '_' matches any one character, including the newline. /// /// \attention To match any character except the newline, use ~_n proto::terminal::type const _ = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Reference to the current regex object /// /// Useful when constructing recursive regular expression objects. The 'self' /// identifier is a short-hand for the current regex object. For instance, /// sregex rx = '(' >> (self | nil) >> ')'; will create a regex object that /// matches balanced parens such as "((()))". proto::terminal::type const self = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Used to create character sets. /// /// There are two ways to create character sets with the 'set' identifier. The /// easiest is to create a comma-separated list of the characters in the set, /// as in (set= 'a','b','c'). This set will match 'a', 'b', or 'c'. The other /// way is to define the set as an argument to the set subscript operator. /// For instance, set[ 'a' | range('b','c') | digit ] will match an 'a', 'b', /// 'c' or a digit character. /// /// To complement a set, apply the '~' operator. For instance, ~(set= 'a','b','c') /// will match any character that is not an 'a', 'b', or 'c'. /// /// Sets can be composed of other, possibly complemented, sets. For instance, /// set[ ~digit | ~(set= 'a','b','c') ]. detail::set_initializer_type const set = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Sub-match placeholder type, used to create named captures in /// static regexes. /// /// \c mark_tag is the type of the global sub-match placeholders \c s0, \c s1, etc.. You /// can use the \c mark_tag type to create your own sub-match placeholders with /// more meaningful names. This is roughly equivalent to the "named capture" /// feature of dynamic regular expressions. /// /// To create a named sub-match placeholder, initialize it with a unique integer. /// The integer must only be unique within the regex in which the placeholder /// is used. Then you can use it within static regexes to created sub-matches /// by assigning a sub-expression to it, or to refer back to already created /// sub-matches. /// /// \code /// mark_tag number(1); // "number" is now equivalent to "s1" /// // Match a number, followed by a space and the same number again /// sregex rx = (number = +_d) >> ' ' >> number; /// \endcode /// /// After a successful \c regex_match() or \c regex_search(), the sub-match placeholder /// can be used to index into the match_results\<\> object to retrieve the /// corresponding sub-match. struct mark_tag : proto::extends { private: typedef proto::extends base_type; static detail::basic_mark_tag make_tag(int mark_nbr) { detail::basic_mark_tag mark = {{mark_nbr}}; return mark; } public: /// \brief Initialize a mark_tag placeholder /// \param mark_nbr An integer that uniquely identifies this \c mark_tag /// within the static regexes in which this \c mark_tag will be used. /// \pre mark_nbr \> 0 mark_tag(int mark_nbr) : base_type(mark_tag::make_tag(mark_nbr)) { // Marks numbers must be integers greater than 0. BOOST_ASSERT(mark_nbr > 0); } /// INTERNAL ONLY operator detail::basic_mark_tag const &() const { return this->proto_base(); } BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT(mark_tag) }; // This macro is used when declaring mark_tags that are global because // it guarantees that they are statically initialized. That avoids // order-of-initialization bugs. In user code, the simpler: mark_tag s0(0); // would be preferable. /// INTERNAL ONLY #define BOOST_XPRESSIVE_GLOBAL_MARK_TAG(NAME, VALUE) \ boost::xpressive::mark_tag::proto_base_expr const NAME = {{VALUE}} \ /**/ /////////////////////////////////////////////////////////////////////////////// /// \brief Sub-match placeholder, like $& in Perl BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s0, 0); /////////////////////////////////////////////////////////////////////////////// /// \brief Sub-match placeholder, like $1 in perl. /// /// To create a sub-match, assign a sub-expression to the sub-match placeholder. /// For instance, (s1= _) will match any one character and remember which /// character was matched in the 1st sub-match. Later in the pattern, you can /// refer back to the sub-match. For instance, (s1= _) >> s1 will match any /// character, and then match the same character again. /// /// After a successful regex_match() or regex_search(), the sub-match placeholders /// can be used to index into the match_results\<\> object to retrieve the Nth /// sub-match. BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s1, 1); BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s2, 2); BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s3, 3); BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s4, 4); BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s5, 5); BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s6, 6); BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s7, 7); BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s8, 8); BOOST_XPRESSIVE_GLOBAL_MARK_TAG(s9, 9); // NOTE: For the purpose of xpressive's documentation, make icase() look like an // ordinary function. In reality, it is a function object defined in detail/icase.hpp // so that it can serve double-duty as regex_constants::icase, the syntax_option_type. #ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED /////////////////////////////////////////////////////////////////////////////// /// \brief Makes a sub-expression case-insensitive. /// /// Use icase() to make a sub-expression case-insensitive. For instance, /// "foo" >> icase(set['b'] >> "ar") will match "foo" exactly followed by /// "bar" irrespective of case. template detail::unspecified icase(Expr const &expr) { return 0; } #endif /////////////////////////////////////////////////////////////////////////////// /// \brief Makes a literal into a regular expression. /// /// Use as_xpr() to turn a literal into a regular expression. For instance, /// "foo" >> "bar" will not compile because both operands to the right-shift /// operator are const char*, and no such operator exists. Use as_xpr("foo") >> "bar" /// instead. /// /// You can use as_xpr() with character literals in addition to string literals. /// For instance, as_xpr('a') will match an 'a'. You can also complement a /// character literal, as with ~as_xpr('a'). This will match any one character /// that is not an 'a'. #ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED template detail::unspecified as_xpr(Literal const &literal) { return 0; } #else proto::functional::as_expr<> const as_xpr = {}; #endif /////////////////////////////////////////////////////////////////////////////// /// \brief Embed a regex object by reference. /// /// \param rex The basic_regex object to embed by reference. template inline typename proto::terminal const> >::type const by_ref(basic_regex const &rex) { reference_wrapper const> ref(rex); return proto::terminal const> >::type::make(ref); } /////////////////////////////////////////////////////////////////////////////// /// \brief Match a range of characters. /// /// Match any character in the range [ch_min, ch_max]. /// /// \param ch_min The lower end of the range to match. /// \param ch_max The upper end of the range to match. template inline typename proto::terminal >::type const range(Char ch_min, Char ch_max) { detail::range_placeholder that = {ch_min, ch_max, false}; return proto::terminal >::type::make(that); } /////////////////////////////////////////////////////////////////////////////// /// \brief Make a sub-expression optional. Equivalent to !as_xpr(expr). /// /// \param expr The sub-expression to make optional. template typename proto::result_of::make_expr< proto::tag::logical_not , proto::default_domain , Expr const & >::type const optional(Expr const &expr) { return proto::make_expr< proto::tag::logical_not , proto::default_domain >(boost::ref(expr)); } /////////////////////////////////////////////////////////////////////////////// /// \brief Repeat a sub-expression multiple times. /// /// There are two forms of the repeat\<\>() function template. To match a /// sub-expression N times, use repeat\(expr). To match a sub-expression /// from M to N times, use repeat\(expr). /// /// The repeat\<\>() function creates a greedy quantifier. To make the quantifier /// non-greedy, apply the unary minus operator, as in -repeat\(expr). /// /// \param expr The sub-expression to repeat. template typename proto::result_of::make_expr< detail::generic_quant_tag , proto::default_domain , Expr const & >::type const repeat(Expr const &expr) { return proto::make_expr< detail::generic_quant_tag , proto::default_domain >(boost::ref(expr)); } /// \overload /// template typename proto::result_of::make_expr< detail::generic_quant_tag , proto::default_domain , Expr2 const & >::type const repeat(Expr2 const &expr2) { return proto::make_expr< detail::generic_quant_tag , proto::default_domain >(boost::ref(expr2)); } /////////////////////////////////////////////////////////////////////////////// /// \brief Create an independent sub-expression. /// /// Turn off back-tracking for a sub-expression. Any branches or repeats within /// the sub-expression will match only one way, and no other alternatives are /// tried. /// /// \attention keep(expr) is equivalent to the perl (?>...) extension. /// /// \param expr The sub-expression to modify. template typename proto::result_of::make_expr< detail::keeper_tag , proto::default_domain , Expr const & >::type const keep(Expr const &expr) { return proto::make_expr< detail::keeper_tag , proto::default_domain >(boost::ref(expr)); } /////////////////////////////////////////////////////////////////////////////// /// \brief Look-ahead assertion. /// /// before(expr) succeeds if the expr sub-expression would match at the current /// position in the sequence, but expr is not included in the match. For instance, /// before("foo") succeeds if we are before a "foo". Look-ahead assertions can be /// negated with the bit-compliment operator. /// /// \attention before(expr) is equivalent to the perl (?=...) extension. /// ~before(expr) is a negative look-ahead assertion, equivalent to the /// perl (?!...) extension. /// /// \param expr The sub-expression to put in the look-ahead assertion. template typename proto::result_of::make_expr< detail::lookahead_tag , proto::default_domain , Expr const & >::type const before(Expr const &expr) { return proto::make_expr< detail::lookahead_tag , proto::default_domain >(boost::ref(expr)); } /////////////////////////////////////////////////////////////////////////////// /// \brief Look-behind assertion. /// /// after(expr) succeeds if the expr sub-expression would match at the current /// position minus N in the sequence, where N is the width of expr. expr is not included in /// the match. For instance, after("foo") succeeds if we are after a "foo". Look-behind /// assertions can be negated with the bit-complement operator. /// /// \attention after(expr) is equivalent to the perl (?<=...) extension. /// ~after(expr) is a negative look-behind assertion, equivalent to the /// perl (? typename proto::result_of::make_expr< detail::lookbehind_tag , proto::default_domain , Expr const & >::type const after(Expr const &expr) { return proto::make_expr< detail::lookbehind_tag , proto::default_domain >(boost::ref(expr)); } /////////////////////////////////////////////////////////////////////////////// /// \brief Specify a regex traits or a std::locale. /// /// imbue() instructs the regex engine to use the specified traits or locale /// when matching the regex. The entire expression must use the same traits/locale. /// For instance, the following specifies a locale for use with a regex: /// std::locale loc; /// sregex rx = imbue(loc)(+digit); /// /// \param loc The std::locale or regex traits object. template inline detail::modifier_op > const imbue(Locale const &loc) { detail::modifier_op > mod = { detail::locale_modifier(loc) , regex_constants::ECMAScript }; return mod; } proto::terminal > >::type const a1 = {{}}; proto::terminal > >::type const a2 = {{}}; proto::terminal > >::type const a3 = {{}}; proto::terminal > >::type const a4 = {{}}; proto::terminal > >::type const a5 = {{}}; proto::terminal > >::type const a6 = {{}}; proto::terminal > >::type const a7 = {{}}; proto::terminal > >::type const a8 = {{}}; proto::terminal > >::type const a9 = {{}}; /////////////////////////////////////////////////////////////////////////////// /// \brief Specify which characters to skip when matching a regex. /// /// skip() instructs the regex engine to skip certain characters when matching /// a regex. It is most useful for writing regexes that ignore whitespace. /// For instance, the following specifies a regex that skips whitespace and /// punctuation: /// /// \code /// // A sentence is one or more words separated by whitespace /// // and punctuation. /// sregex word = +alpha; /// sregex sentence = skip(set[_s | punct])( +word ); /// \endcode /// /// The way it works in the above example is to insert /// keep(*set[_s | punct]) before each primitive within the regex. /// A "primitive" includes terminals like strings, character sets and nested /// regexes. A final *set[_s | punct] is added to the end of the /// regex. The regex sentence specified above is equivalent to /// the following: /// /// \code /// sregex sentence = +( keep(*set[_s | punct]) >> word ) /// >> *set[_s | punct]; /// \endcode /// /// \attention Skipping does not affect how nested regexes are handled because /// they are treated atomically. String literals are also treated /// atomically; that is, no skipping is done within a string literal. So /// skip(_s)("this that") is not the same as /// skip(_s)("this" >> as_xpr("that")). The first will only match /// when there is only one space between "this" and "that". The second will /// skip any and all whitespace between "this" and "that". /// /// \param skip A regex that specifies which characters to skip. template detail::skip_directive skip(Skip const &skip) { return detail::skip_directive(skip); } namespace detail { inline void ignore_unused_regex_primitives() { detail::ignore_unused(repeat_max); detail::ignore_unused(inf); detail::ignore_unused(epsilon); detail::ignore_unused(nil); detail::ignore_unused(alnum); detail::ignore_unused(bos); detail::ignore_unused(eos); detail::ignore_unused(bol); detail::ignore_unused(eol); detail::ignore_unused(bow); detail::ignore_unused(eow); detail::ignore_unused(_b); detail::ignore_unused(_w); detail::ignore_unused(_d); detail::ignore_unused(_s); detail::ignore_unused(_n); detail::ignore_unused(_ln); detail::ignore_unused(_); detail::ignore_unused(self); detail::ignore_unused(set); detail::ignore_unused(s0); detail::ignore_unused(s1); detail::ignore_unused(s2); detail::ignore_unused(s3); detail::ignore_unused(s4); detail::ignore_unused(s5); detail::ignore_unused(s6); detail::ignore_unused(s7); detail::ignore_unused(s8); detail::ignore_unused(s9); detail::ignore_unused(a1); detail::ignore_unused(a2); detail::ignore_unused(a3); detail::ignore_unused(a4); detail::ignore_unused(a5); detail::ignore_unused(a6); detail::ignore_unused(a7); detail::ignore_unused(a8); detail::ignore_unused(a9); detail::ignore_unused(as_xpr); } } }} // namespace boost::xpressive #endif