toy_spirit.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 668 行 · 第 1/2 页

CPP
668
字号
                this->in_skip_ = false;            }        }        Skipper skip_;        bool in_skip_;    };    struct as_ichar_parser : proto::callable    {        typedef proto::function<            ianychar_p          , proto::terminal<char>::type          , proto::terminal<char>::type        >::type result_type;        template<typename Expr>        result_type operator()(Expr const &expr) const        {            char lo = std::tolower(proto::value(proto::child_c<1>(expr)));            char hi = std::toupper(proto::value(proto::child_c<1>(expr)));            result_type that = {ichar_, {lo}, {hi}};            return that;        }    };    struct as_ichar_range_parser : proto::callable    {        typedef proto::function<            ianychar_range_p          , proto::terminal<char>::type          , proto::terminal<char>::type        >::type result_type;        template<typename Expr>        result_type operator()(Expr const &expr) const        {            char lo = proto::value(proto::child_c<1>(expr));            char hi = proto::value(proto::child_c<2>(expr));            result_type that = {ichar_range_, {lo}, {hi}};            return that;        }    };    struct as_ichar_literal : proto::callable    {        typedef proto::function<            ianychar_p          , proto::terminal<char>::type          , proto::terminal<char>::type        >::type result_type;        template<typename Expr>        result_type operator()(Expr const &expr) const        {            char lo = std::tolower(proto::value(expr));            char hi = std::toupper(proto::value(expr));            result_type that = {ichar_, {lo}, {hi}};            return that;        }    };    struct as_intbs_literal : proto::callable    {        typedef proto::function<            ianystr_p          , proto::terminal<std::string>::type        >::type result_type;        template<typename Expr>        result_type operator()(Expr const &expr) const        {            result_type that = {istr_, {utility::to_istr(proto::value(expr))}};            return that;        }    };    struct as_istdstring_literal : proto::callable    {        typedef proto::function<            ianystr_p          , proto::terminal<std::string>::type        >::type result_type;        template<typename Expr>        result_type operator()(Expr const &expr) const        {            result_type that = {istr_, {utility::to_istr(proto::value(expr).c_str())}};            return that;        }    };    ///////////////////////////////////////////////////////////////////////////    // Transforms    ///////////////////////////////////////////////////////////////////////////    struct skip_primitives : proto::transform<skip_primitives>    {        template<typename Expr, typename State, typename Data>        struct impl : proto::transform_impl<Expr, State, Data>        {            typedef                typename proto::shift_right<                    typename proto::dereference<State>::type                  , Expr                >::type            result_type;            result_type operator ()(                typename impl::expr_param expr              , typename impl::state_param state              , typename impl::data_param data            ) const            {                result_type that = {{state}, expr};                return that;            }        };    };    ///////////////////////////////////////////////////////////////////////////    // Grammar    ///////////////////////////////////////////////////////////////////////////    using proto::_;    struct SpiritGrammar;    struct SpiritCaseSensitivePrimitives      : proto::or_<            proto::when<CharParser, as_ichar_parser(_)>          , proto::when<CharLiteral, as_ichar_literal(_)>          , proto::when<NTBSLiteral, as_intbs_literal(_)>          , proto::when<CharRangeParser, as_ichar_range_parser(_)>          , proto::when<StdStringLiteral, as_istdstring_literal(_)>        >    {};    struct SpiritCaseInsensitivePrimitives      : proto::or_<            anychar_p          , IStrParser          , ICharParser          , ICharRangeParser          , proto::complement<SpiritPrimitives>        >    {};    struct SpiritPrimitives      : proto::or_<            SpiritCaseSensitivePrimitives          , SpiritCaseInsensitivePrimitives        >    {};    template<typename Grammar>    struct SpiritComposites      : proto::or_<            proto::bitwise_or< Grammar, Grammar >          , proto::shift_right< Grammar, Grammar >          , proto::minus< Grammar, Grammar >          , proto::dereference< Grammar >          , proto::unary_plus< Grammar >          , proto::logical_not< Grammar >        >    {};    // Regular Spirit grammar, has no-case transforms    struct SpiritGrammar      : proto::or_<            SpiritComposites<SpiritGrammar>          , SpiritPrimitives        >    {};    // Spirit grammar with the skipper transform    struct SkipperGrammar      : proto::or_<            SpiritComposites<SkipperGrammar>          , proto::when<SpiritPrimitives, skip_primitives>        >    {};    ///////////////////////////////////////////////////////////////////////////    // Directives    ///////////////////////////////////////////////////////////////////////////    struct no_case_directive    {        template<typename Expr>        typename SpiritGrammar::result<void(Expr, mpl::void_, mpl::void_)>::type const        operator [](Expr const &expr) const        {            mpl::void_ null;            return SpiritGrammar()(expr, null, null);        }    };    // no_case    no_case_directive const no_case = {};    template<typename Skipper>    struct skip_directive    {        skip_directive(Skipper const &skip)          : skip_(skip)        {}        template<typename Expr>        typename boost::result_of<SkipperGrammar(Expr const &, Skipper const &, mpl::void_ &)>::type const        operator [](Expr const &expr) const        {            mpl::void_ null;            return SkipperGrammar()(expr, this->skip_, null);        }    private:        Skipper skip_;    };    // skip    template<typename Skipper>    skip_directive<Skipper> skip(Skipper const &skip)    {        return skip_directive<Skipper>(skip);    }    ///////////////////////////////////////////////////////////////////////////    // parse    ///////////////////////////////////////////////////////////////////////////    template<typename FwdIter, typename Rule>    bool parse(FwdIter begin, FwdIter end, Rule const &rule)    {        // make sure the rule corresponds to the Spirit grammar:        BOOST_MPL_ASSERT((proto::matches<Rule, SpiritGrammar>));        spirit_context<FwdIter> ctx(begin, end);        return proto::eval(rule, ctx);    }    // parse with a skip parser can be implemented in one of two ways:    // Method 1)    //      The skip parser is passed to all the parsers which invoke it    //      before they invoke themselves. This is how Spirit-1 does it,    //      and it is the cause of the Scanner Business. However, it has    //      the advantage of not needing a parser transformation phase.    // Method 2)    //      Transform the expression template to insert the skip parser    //      in between all sequenced parsers. That is, transform (A >> B)    //      to (*skip >> A >> *skip >> B). This has the advantage of making    //      it unnecessary to pass the scanner to all the parsers, which    //      means its type doesn't show up in function signatures, avoiding    //      the Scanner Business.    // Recommendation:    //      Both methods should be supported. Method 1 should be preferred    //      when calling parse with parsers defined inline. Method 2 should    //      be preferred when a parser expression is assigned to a rule<>,    //      thereby making the type of the rule<> independent of the skip    //      parser used. I imagine a syntax like:    //          rule<> r = skip(space)[A >> B >> C]    template<typename FwdIter, typename Rule, typename Skipper>    bool parse(FwdIter begin, FwdIter end, Rule const &rule, Skipper const &skipper)    {        // make sure the rule corresponds to the Spirit grammar:        BOOST_MPL_ASSERT((proto::matches<Rule, SpiritGrammar>));        //// Method 1: pass skip parser in the context structure.        //spirit_context<FwdIter, Skipper> ctx(begin, end, skipper);        //return proto::eval(rule, ctx);        // Method 2: Embed skip parser via tree transformation.        spirit_context<FwdIter> ctx(begin, end);        return proto::eval(spirit2::skip(skipper)[rule], ctx);    }}}using namespace boost;using namespace spirit2;void test_toy_spirit(){    std::string str("abcd");    // This will fail:    BOOST_CHECK(!spirit2::parse(str.begin(), str.end()                   , char_ >> char_('a')));    // This will succeed:    BOOST_CHECK(spirit2::parse(str.begin(), str.end()                   , char_ >> char_('b') >> char_ >> 'd'));    // This will succeed:    BOOST_CHECK(spirit2::parse(str.begin(), str.end()                   , 'a' >> ('c' >> char_ | 'b' >> char_('d') | 'b' >> char_('c')) >> 'd'));    // This will succeed:    BOOST_CHECK(spirit2::parse(str.begin(), str.end()                   , *(char_ - 'd')));    // This will succeed:    BOOST_CHECK(spirit2::parse(str.begin(), str.end()                   , no_case[char_('A') >> 'B' >> "CD"]));    // This will succeed:    BOOST_CHECK(spirit2::parse(str.begin(), str.end()                   , no_case[*char_('A','Z')]));    literal<char> a = lit('a');    literal<char const *> bcd = lit("bcd");    // This will succeed:    BOOST_CHECK(spirit2::parse(str.begin(), str.end()                   , +~~a >> no_case[bcd]));    // Scanner Business: R.I.P. :-)    str = "a  b    cd";    BOOST_CHECK(spirit2::parse(str.begin(), str.end()                   , char_('a') >> 'b' >> 'c' >> 'd', space >> space));}using namespace boost::unit_test;///////////////////////////////////////////////////////////////////////////////// init_unit_test_suite//test_suite* init_unit_test_suite( int argc, char* argv[] ){    test_suite *test = BOOST_TEST_SUITE("test proto and and toy spirit-2");    test->add(BOOST_TEST_CASE(&test_toy_spirit));    return test;}

⌨️ 快捷键说明

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