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 + -
显示快捷键?