toy_spirit.cpp

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

CPP
668
字号
///////////////////////////////////////////////////////////////////////////////// toy_spirit.hpp////  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)#include <cctype>#include <string>#include <cstring>#include <iostream>#include <boost/assert.hpp>#include <boost/mpl/assert.hpp>#include <boost/xpressive/proto/proto.hpp>#include <boost/xpressive/proto/context.hpp>#include <boost/test/unit_test.hpp>namespace boost{    // global tags    struct char_tag {};    struct ichar_tag {};    struct istring_tag {};    struct ichar_range_tag {};    struct never_tag {};    struct always_tag {};    struct space_tag {};    // global primitives    proto::terminal<char_tag>::type const char_ = {{}};    proto::terminal<space_tag>::type const space = {{}};    using proto::lit;    using proto::literal;}namespace boost { namespace spirit2{    // handy typedefs    typedef proto::terminal<char_tag>::type anychar_p;    typedef proto::terminal<ichar_tag>::type ianychar_p;    typedef proto::terminal<istring_tag>::type ianystr_p;    typedef proto::terminal<ichar_range_tag>::type ianychar_range_p;    typedef proto::terminal<never_tag>::type never_p;    typedef proto::terminal<space_tag>::type space_p;    struct SpiritGrammar;    struct SkipperGrammar;    struct SpiritPrimitives;    template<typename Grammar>    struct SpiritComposites;    struct CharLiteral      : proto::terminal<char>    {};    struct NTBSLiteral      : proto::terminal<char const *>    {};    struct StdStringLiteral      : proto::terminal<std::string>    {};    struct CharParser      : proto::function<anychar_p, CharLiteral>    {};    struct ICharParser      : proto::function<ianychar_p, CharLiteral, CharLiteral>    {};    struct CharRangeParser      : proto::function<anychar_p, CharLiteral, CharLiteral>    {};    struct IStrParser      : proto::function<ianystr_p, StdStringLiteral>    {};    struct ICharRangeParser      : proto::function<ianychar_range_p, CharLiteral, CharLiteral>    {};    ianychar_p const ichar_ = {{}};    ianystr_p const istr_ = {{}};    ianychar_range_p const ichar_range_ = {{}};    namespace utility    {        inline bool char_icmp(char ch, char lo, char hi)        {            return ch == lo || ch == hi;        }        template<typename FwdIter>        inline bool string_cmp(char const *sz, FwdIter &begin, FwdIter end)        {            FwdIter tmp = begin;            for(; *sz; ++tmp, ++sz)                if(tmp == end || *tmp != *sz)                    return false;            begin = tmp;            return true;        }        template<typename FwdIter>        inline bool string_icmp(std::string const &str, FwdIter &begin, FwdIter end)        {            BOOST_ASSERT(0 == str.size() % 2);            FwdIter tmp = begin;            std::string::const_iterator istr = str.begin(), estr = str.end();            for(; istr != estr; ++tmp, istr += 2)                if(tmp == end || *tmp != *istr && *tmp != *(istr+1))                    return false;            begin = tmp;            return true;        }        inline bool in_range(char ch, char lo, char hi)        {            return ch >= lo && ch <= hi;        }        inline bool in_irange(char ch, char lo, char hi)        {            return in_range(ch, lo, hi)                || in_range(std::tolower(ch), lo, hi)                || in_range(std::toupper(ch), lo, hi);        }        inline std::string to_istr(char const *sz)        {            std::string res;            res.reserve(std::strlen(sz) * 2);            for(; *sz; ++sz)            {                res.push_back(std::tolower(*sz));                res.push_back(std::toupper(*sz));            }            return res;        }    } // namespace utility    template<typename FwdIter, typename Skipper = never_p>    struct spirit_context      : std::pair<FwdIter, FwdIter>      , proto::callable_context<spirit_context<FwdIter, Skipper> >    {        typedef bool result_type;        typedef FwdIter iterator;        spirit_context(FwdIter first, FwdIter second, Skipper const &skip = Skipper())          : std::pair<FwdIter, FwdIter>(first, second)          , skip_(skip)          , in_skip_(false)        {}        // parse function for anychar_p        bool operator()(proto::tag::terminal, char_tag)        {            this->skip();            if(this->first == this->second)                return false;            ++this->first;            return true;        }        // parse function for char_('a')        template<typename Expr>        bool operator()(proto::tag::function, anychar_p, Expr const &expr)        {            this->skip();            return proto::eval(expr, *this);        }        // parse function for space_p        bool operator()(proto::tag::terminal, space_tag)        {            this->skip();            if(this->first == this->second || !std::isspace(*this->first))                return false;            ++this->first;            return true;        }        // parse function for bare character literals        bool operator()(proto::tag::terminal, char ch)        {            this->skip();            if(this->first == this->second || *this->first != ch)                return false;            ++this->first;            return true;        }        // case-insensitive character parser        template<typename Arg1, typename Arg2>        bool operator()(proto::tag::function, ianychar_p, Arg1 const &arg1, Arg2 const &arg2)        {            this->skip();            if(this->first == this->second              || !utility::char_icmp(*this->first, proto::arg(arg1), proto::arg(arg2)))                return false;            ++this->first;            return true;        }        // parse function for NTBS literals        bool operator()(proto::tag::terminal, char const *sz)        {            this->skip();            return utility::string_cmp(sz, this->first, this->second);        }        // parse function for istr_("hello")        template<typename Expr>        bool operator()(proto::tag::function, ianystr_p, Expr const &expr)        {            this->skip();            return utility::string_icmp(proto::arg(expr), this->first, this->second);        }        // parse function for char_('a','z')        template<typename Arg1, typename Arg2>        bool operator()(proto::tag::function, anychar_p, Arg1 const &arg1, Arg2 const &arg2)        {            BOOST_ASSERT(proto::arg(arg1) <= proto::arg(arg2));            this->skip();            if(this->first == this->second              || !utility::in_range(*this->first, proto::arg(arg1), proto::arg(arg2)))                return false;            ++this->first;            return true;        }        // parse function for ichar_range_('a','z')        template<typename Arg1, typename Arg2>        bool operator()(proto::tag::function, ianychar_range_p, Arg1 const &arg1, Arg2 const &arg2)        {            BOOST_ASSERT(proto::arg(arg1) <= proto::arg(arg2));            this->skip();            if(this->first == this->second              || !utility::in_irange(*this->first, proto::arg(arg1), proto::arg(arg2)))                return false;            ++this->first;            return true;        }        // parse function for complemented thingies (where thingies are assumed        // to be 1 character wide).        template<typename Expr>        bool operator()(proto::tag::complement, Expr const &expr)        {            this->skip();            iterator where = this->first;            if(proto::eval(expr, *this))                return this->first = where, false;            this->first = ++where;            return true;        }        // never_p parse function always returns false.        bool operator()(proto::tag::terminal, never_tag)        {            return false;        }        // for A >> B, succeeds if A and B matches.        template<typename Left, typename Right>        bool operator()(proto::tag::shift_right, Left const &left, Right const &right)        {            return proto::eval(left, *this) && proto::eval(right, *this);        }        // for A | B, succeeds if either A or B matches at this point.        template<typename Left, typename Right>        bool operator()(proto::tag::bitwise_or, Left const &left, Right const &right)        {            iterator where = this->first;            return proto::eval(left, *this) || proto::eval(right, this->reset(where));        }        // for *A, greedily match A as many times as possible.        template<typename Expr>        bool operator()(proto::tag::dereference, Expr const &expr)        {            iterator where = this->first;            while(proto::eval(expr, *this))                where = this->first;            // make sure that when we return true, the iterator is at the correct position!            this->first = where;            return true;        }        // for +A, greedily match A one or more times.        template<typename Expr>        bool operator()(proto::tag::posit, Expr const &expr)        {            return proto::eval(expr, *this) && proto::eval(*expr, *this);        }        // for !A, optionally match A.        template<typename Expr>        bool operator()(proto::tag::logical_not, Expr const &expr)        {            iterator where = this->first;            if(!proto::eval(expr, *this))                this->first = where;            return true;        }        // for (A - B), matches when A but not B matches.        template<typename Left, typename Right>        bool operator()(proto::tag::minus, Left const &left, Right const &right)        {            iterator where = this->first;            return !proto::eval(right, *this) && proto::eval(left, this->reset(where));        }    private:        spirit_context &reset(iterator where)        {            this->first = where;            return *this;        }        void skip()        {            if(!this->in_skip_)            {                this->in_skip_ = true;                while(proto::eval(this->skip_, *this))                {}

⌨️ 快捷键说明

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