confix.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 397 行

HPP
397
字号
/*=============================================================================    Copyright (c) 2002-2003 Hartmut Kaiser    http://spirit.sourceforge.net/  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_SPIRIT_CONFIX_HPP#define BOOST_SPIRIT_CONFIX_HPP///////////////////////////////////////////////////////////////////////////////#include <boost/config.hpp>#include <boost/spirit/home/classic/namespace.hpp>#include <boost/spirit/home/classic/meta/as_parser.hpp>#include <boost/spirit/home/classic/core/composite/operators.hpp>#include <boost/spirit/home/classic/utility/confix_fwd.hpp>#include <boost/spirit/home/classic/utility/impl/confix.ipp>///////////////////////////////////////////////////////////////////////////////namespace boost { namespace spirit {BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN///////////////////////////////////////////////////////////////////////////////////  confix_parser class////      Parses a sequence of 3 sub-matches. This class may//      be used to parse structures, where the opening part is possibly//      contained in the expression part and the whole sequence is only//      parsed after seeing the closing part matching the first opening//      subsequence. Example: C-comments:////      /* This is a C-comment *//////////////////////////////////////////////////////////////////////////////////template<typename NestedT = non_nested, typename LexemeT = non_lexeme>struct confix_parser_gen;template <    typename OpenT, typename ExprT, typename CloseT, typename CategoryT,    typename NestedT, typename LexemeT>struct confix_parser :    public parser<        confix_parser<OpenT, ExprT, CloseT, CategoryT, NestedT, LexemeT>    >{    typedef        confix_parser<OpenT, ExprT, CloseT, CategoryT, NestedT, LexemeT>        self_t;    confix_parser(OpenT const &open_, ExprT const &expr_, CloseT const &close_)    : open(open_), expr(expr_), close(close_)    {}    template <typename ScannerT>    typename parser_result<self_t, ScannerT>::type    parse(ScannerT const& scan) const    {        return impl::confix_parser_type<CategoryT>::            parse(NestedT(), LexemeT(), *this, scan, open, expr, close);    }private:    typename as_parser<OpenT>::type::embed_t open;    typename as_parser<ExprT>::type::embed_t expr;    typename as_parser<CloseT>::type::embed_t close;};///////////////////////////////////////////////////////////////////////////////////  Confix parser generator template////      This is a helper for generating a correct confix_parser<> from//      auxiliary parameters. There are the following types supported as//      parameters yet: parsers, single characters and strings (see//      as_parser).////      If the body parser is an action_parser_category type parser (a parser//      with an attached semantic action) we have to do something special. This//      happens, if the user wrote something like:////          confix_p(open, body[f], close)////      where 'body' is the parser matching the body of the confix sequence//      and 'f' is a functor to be called after matching the body. If we would//      do nothing, the resulting code would parse the sequence as follows:////          start >> (body[f] - close) >> close////      what in most cases is not what the user expects.//      (If this _is_ what you've expected, then please use the confix_p//      generator function 'direct()', which will inhibit//      re-attaching the actor to the body parser).////      To make the confix parser behave as expected:////          start >> (body - close)[f] >> close////      the actor attached to the 'body' parser has to be re-attached to the//      (body - close) parser construct, which will make the resulting confix//      parser 'do the right thing'. This refactoring is done by the help of//      the refactoring parsers (see the files refactoring.[hi]pp).////      Additionally special care must be taken, if the body parser is a//      unary_parser_category type parser as////          confix_p(open, *anychar_p, close)////      which without any refactoring would result in////          start >> (*anychar_p - close) >> close////      and will not give the expected result (*anychar_p will eat up all the//      input up to the end of the input stream). So we have to refactor this//      into:////          start >> *(anychar_p - close) >> close////      what will give the correct result.////      The case, where the body parser is a combination of the two mentioned//      problems (i.e. the body parser is a unary parser  with an attached//      action), is handled accordingly too:////          confix_p(start, (*anychar_p)[f], end)////      will be parsed as expected:////          start >> (*(anychar_p - end))[f] >> end./////////////////////////////////////////////////////////////////////////////////template<typename NestedT, typename LexemeT>struct confix_parser_gen{    // Generic generator function for creation of concrete confix parsers    template<typename StartT, typename ExprT, typename EndT>    struct paren_op_result_type    {        typedef confix_parser<            typename as_parser<StartT>::type,            typename as_parser<ExprT>::type,            typename as_parser<EndT>::type,            typename as_parser<ExprT>::type::parser_category_t,            NestedT,            LexemeT        > type;    };      template<typename StartT, typename ExprT, typename EndT>    typename paren_op_result_type<StartT, ExprT, EndT>::type     operator()(StartT const &start_, ExprT const &expr_, EndT const &end_) const    {        typedef typename paren_op_result_type<StartT,ExprT,EndT>::type             return_t;        return return_t(            as_parser<StartT>::convert(start_),            as_parser<ExprT>::convert(expr_),            as_parser<EndT>::convert(end_)        );    }    // Generic generator function for creation of concrete confix parsers    // which have an action directly attached to the ExprT part of the    // parser (see comment above, no automatic refactoring)    template<typename StartT, typename ExprT, typename EndT>    struct direct_result_type    {        typedef confix_parser<            typename as_parser<StartT>::type,            typename as_parser<ExprT>::type,            typename as_parser<EndT>::type,            plain_parser_category,   // do not re-attach action            NestedT,            LexemeT        > type;    };    template<typename StartT, typename ExprT, typename EndT>    typename direct_result_type<StartT,ExprT,EndT>::type    direct(StartT const &start_, ExprT const &expr_, EndT const &end_) const    {        typedef typename direct_result_type<StartT,ExprT,EndT>::type            return_t;        return return_t(            as_parser<StartT>::convert(start_),            as_parser<ExprT>::convert(expr_),            as_parser<EndT>::convert(end_)        );    }};///////////////////////////////////////////////////////////////////////////////////  Predefined non_nested confix parser generators/////////////////////////////////////////////////////////////////////////////////const confix_parser_gen<non_nested, non_lexeme> confix_p =    confix_parser_gen<non_nested, non_lexeme>();///////////////////////////////////////////////////////////////////////////////////  Comments are special types of confix parsers////      Comment parser generator template. This is a helper for generating a//      correct confix_parser<> from auxiliary parameters, which is able to//      parse comment constructs: (StartToken >> Comment text >> EndToken).////      There are the following types supported as parameters yet: parsers,//      single characters and strings (see as_parser).////      There are two diffenerent predefined comment parser generators//      (comment_p and comment_nest_p, see below), which may be used for//      creating special comment parsers in two different ways.////      If these are used with one parameter, a comment starting with the given//      first parser parameter up to the end of the line is matched. So for//      instance the following parser matches C++ style comments:////          comment_p("//").////      If these are used with two parameters, a comment starting with the//      first parser parameter up to the second parser parameter is matched.//      For instance a C style comment parser should be constrcuted as:////          comment_p("/*", "*/").////      Please note, that a comment is parsed implicitly as if the whole//      comment_p(...) statement were embedded into a lexeme_d[] directive./////////////////////////////////////////////////////////////////////////////////template<typename NestedT>struct comment_parser_gen{    // Generic generator function for creation of concrete comment parsers    // from an open token. The newline parser eol_p is used as the    // closing token.    template<typename StartT>    struct paren_op1_result_type    {        typedef confix_parser<            typename as_parser<StartT>::type,            kleene_star<anychar_parser>,            alternative<eol_parser, end_parser>,            unary_parser_category,          // there is no action to re-attach            NestedT,            is_lexeme                       // insert implicit lexeme_d[]        >        type;    };    template<typename StartT>    typename paren_op1_result_type<StartT>::type     operator() (StartT const &start_) const    {        typedef typename paren_op1_result_type<StartT>::type            return_t;        return return_t(            as_parser<StartT>::convert(start_),            *anychar_p,            eol_p | end_p        );    }    // Generic generator function for creation of concrete comment parsers    // from an open and a close tokens.    template<typename StartT, typename EndT>    struct paren_op2_result_type    {        typedef confix_parser<            typename as_parser<StartT>::type,            kleene_star<anychar_parser>,            typename as_parser<EndT>::type,            unary_parser_category,          // there is no action to re-attach            NestedT,            is_lexeme                       // insert implicit lexeme_d[]        > type;    };    template<typename StartT, typename EndT>    typename paren_op2_result_type<StartT,EndT>::type    operator() (StartT const &start_, EndT const &end_) const    {        typedef typename paren_op2_result_type<StartT,EndT>::type            return_t;        return return_t(            as_parser<StartT>::convert(start_),            *anychar_p,            as_parser<EndT>::convert(end_)        );    }};///////////////////////////////////////////////////////////////////////////////////  Predefined non_nested comment parser generator/////////////////////////////////////////////////////////////////////////////////const comment_parser_gen<non_nested> comment_p =    comment_parser_gen<non_nested>();///////////////////////////////////////////////////////////////////////////////////  comment_nest_parser class////      Parses a nested comments.//      Example: nested PASCAL-comments:////      { This is a { nested } PASCAL-comment }/////////////////////////////////////////////////////////////////////////////////template<typename OpenT, typename CloseT>struct comment_nest_parser:    public parser<comment_nest_parser<OpenT, CloseT> >{    typedef comment_nest_parser<OpenT, CloseT> self_t;    comment_nest_parser(OpenT const &open_, CloseT const &close_):        open(open_), close(close_)    {}    template<typename ScannerT>    typename parser_result<self_t, ScannerT>::type        parse(ScannerT const &scan) const    {        return do_parse(            open >> *(*this | (anychar_p - close)) >> close,            scan);    }private:    template<typename ParserT, typename ScannerT>    typename parser_result<self_t, ScannerT>::type        do_parse(ParserT const &p, ScannerT const &scan) const    {        return            impl::contiguous_parser_parse<                typename parser_result<ParserT, ScannerT>::type            >(p, scan, scan);    }    typename as_parser<OpenT>::type::embed_t open;    typename as_parser<CloseT>::type::embed_t close;};///////////////////////////////////////////////////////////////////////////////////  Predefined nested comment parser generator/////////////////////////////////////////////////////////////////////////////////template<typename OpenT, typename CloseT>struct comment_nest_p_result{    typedef comment_nest_parser<        typename as_parser<OpenT>::type,        typename as_parser<CloseT>::type    > type;};template<typename OpenT, typename CloseT>inline typename comment_nest_p_result<OpenT,CloseT>::type comment_nest_p(OpenT const &open, CloseT const &close){    typedef typename comment_nest_p_result<OpenT,CloseT>::type        result_t;    return result_t(        as_parser<OpenT>::convert(open),        as_parser<CloseT>::convert(close)    );}///////////////////////////////////////////////////////////////////////////////BOOST_SPIRIT_CLASSIC_NAMESPACE_END}} // namespace BOOST_SPIRIT_CLASSIC_NS#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?