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::arg(proto::arg_c<1>(expr)));            char hi = std::toupper(proto::arg(proto::arg_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::arg(proto::arg_c<1>(expr));            char hi = proto::arg(proto::arg_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::arg(expr));            char hi = std::toupper(proto::arg(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::arg(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::arg(expr).c_str())}};            return that;        }    };    ///////////////////////////////////////////////////////////////////////////    // Transforms    ///////////////////////////////////////////////////////////////////////////    struct skip_primitives : proto::callable    {        template<typename Sig>        struct result;        template<typename This, typename Expr, typename State, typename Visitor>        struct result<This(Expr, State, Visitor)>        {            typedef typename proto::shift_right<                typename proto::dereference<State>::type              , Expr            >::type type;        };        template<typename Expr, typename State, typename Visitor>        typename result<void(Expr, State, Visitor)>::type        operator()(Expr const &expr, State const &state, Visitor &visitor) const        {            typedef typename result<void(Expr, State, Visitor)>::type type;            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::posit< 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 SkipperGrammar::result<void(Expr, Skipper, 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 + -
显示快捷键?