mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-26 00:58:09 +00:00
Added thirdparty: boost library
This commit is contained in:
+410
@@ -0,0 +1,410 @@
|
||||
// Copyright (c) 2001-2011 Hartmut Kaiser
|
||||
//
|
||||
// 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)
|
||||
|
||||
#if !defined(BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM)
|
||||
#define BOOST_SPIRIT_LEX_LEXER_MAR_13_2007_0145PM
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/spirit/home/support/info.hpp>
|
||||
#include <boost/spirit/home/qi/skip_over.hpp>
|
||||
#include <boost/spirit/home/qi/parser.hpp>
|
||||
#include <boost/spirit/home/qi/detail/assign_to.hpp>
|
||||
#include <boost/spirit/home/lex/reference.hpp>
|
||||
#include <boost/spirit/home/lex/meta_compiler.hpp>
|
||||
#include <boost/spirit/home/lex/lexer_type.hpp>
|
||||
#include <boost/spirit/home/lex/lexer/token_def.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/fusion/include/vector.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/proto/extends.hpp>
|
||||
#include <boost/proto/traits.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <iterator> // for std::iterator_traits
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace spirit { namespace lex
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
namespace detail
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4512) // assignment operator could not be generated.
|
||||
#endif
|
||||
template <typename LexerDef>
|
||||
struct lexer_def_
|
||||
: proto::extends<
|
||||
typename proto::terminal<
|
||||
lex::reference<lexer_def_<LexerDef> const>
|
||||
>::type
|
||||
, lexer_def_<LexerDef> >
|
||||
, qi::parser<lexer_def_<LexerDef> >
|
||||
, lex::lexer_type<lexer_def_<LexerDef> >
|
||||
{
|
||||
private:
|
||||
// avoid warnings about using 'this' in constructor
|
||||
lexer_def_& this_() { return *this; }
|
||||
|
||||
typedef typename LexerDef::char_type char_type;
|
||||
typedef typename LexerDef::string_type string_type;
|
||||
typedef typename LexerDef::id_type id_type;
|
||||
|
||||
typedef lex::reference<lexer_def_ const> reference_;
|
||||
typedef typename proto::terminal<reference_>::type terminal_type;
|
||||
typedef proto::extends<terminal_type, lexer_def_> proto_base_type;
|
||||
|
||||
reference_ alias() const
|
||||
{
|
||||
return reference_(*this);
|
||||
}
|
||||
|
||||
public:
|
||||
// Qi interface: metafunction calculating parser attribute type
|
||||
template <typename Context, typename Iterator>
|
||||
struct attribute
|
||||
{
|
||||
// the return value of a token set contains the matched token
|
||||
// id, and the corresponding pair of iterators
|
||||
typedef typename Iterator::base_iterator_type iterator_type;
|
||||
typedef
|
||||
fusion::vector2<id_type, iterator_range<iterator_type> >
|
||||
type;
|
||||
};
|
||||
|
||||
// Qi interface: parse functionality
|
||||
template <typename Iterator, typename Context
|
||||
, typename Skipper, typename Attribute>
|
||||
bool parse(Iterator& first, Iterator const& last
|
||||
, Context& /*context*/, Skipper const& skipper
|
||||
, Attribute& attr) const
|
||||
{
|
||||
qi::skip_over(first, last, skipper); // always do a pre-skip
|
||||
|
||||
if (first != last) {
|
||||
typedef typename
|
||||
std::iterator_traits<Iterator>::value_type
|
||||
token_type;
|
||||
|
||||
token_type const& t = *first;
|
||||
if (token_is_valid(t) && t.state() == first.get_state()) {
|
||||
// any of the token definitions matched
|
||||
spirit::traits::assign_to(t, attr);
|
||||
++first;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Qi interface: 'what' functionality
|
||||
template <typename Context>
|
||||
info what(Context& /*context*/) const
|
||||
{
|
||||
return info("lexer");
|
||||
}
|
||||
|
||||
private:
|
||||
// allow to use the lexer.self.add("regex1", id1)("regex2", id2);
|
||||
// syntax
|
||||
struct adder
|
||||
{
|
||||
adder(lexer_def_& def_)
|
||||
: def(def_) {}
|
||||
|
||||
// Add a token definition based on a single character as given
|
||||
// by the first parameter, the second parameter allows to
|
||||
// specify the token id to use for the new token. If no token
|
||||
// id is given the character code is used.
|
||||
adder const& operator()(char_type c
|
||||
, id_type token_id = id_type()) const
|
||||
{
|
||||
if (id_type() == token_id)
|
||||
token_id = static_cast<id_type>(c);
|
||||
def.def.add_token (def.state.c_str(), c, token_id
|
||||
, def.targetstate.empty() ? 0 : def.targetstate.c_str());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Add a token definition based on a character sequence as
|
||||
// given by the first parameter, the second parameter allows to
|
||||
// specify the token id to use for the new token. If no token
|
||||
// id is given this function will generate a unique id to be
|
||||
// used as the token's id.
|
||||
adder const& operator()(string_type const& s
|
||||
, id_type token_id = id_type()) const
|
||||
{
|
||||
if (id_type() == token_id)
|
||||
token_id = def.def.get_next_id();
|
||||
def.def.add_token (def.state.c_str(), s, token_id
|
||||
, def.targetstate.empty() ? 0 : def.targetstate.c_str());
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Attribute>
|
||||
adder const& operator()(
|
||||
token_def<Attribute, char_type, id_type>& tokdef
|
||||
, id_type token_id = id_type()) const
|
||||
{
|
||||
// make sure we have a token id
|
||||
if (id_type() == token_id) {
|
||||
if (id_type() == tokdef.id()) {
|
||||
token_id = def.def.get_next_id();
|
||||
tokdef.id(token_id);
|
||||
}
|
||||
else {
|
||||
token_id = tokdef.id();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the following assertion makes sure that the token_def
|
||||
// instance has not been assigned a different id earlier
|
||||
BOOST_ASSERT(id_type() == tokdef.id()
|
||||
|| token_id == tokdef.id());
|
||||
tokdef.id(token_id);
|
||||
}
|
||||
|
||||
def.define(tokdef);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// template <typename F>
|
||||
// adder const& operator()(char_type c, id_type token_id, F act) const
|
||||
// {
|
||||
// if (id_type() == token_id)
|
||||
// token_id = def.def.get_next_id();
|
||||
// std::size_t unique_id =
|
||||
// def.def.add_token (def.state.c_str(), s, token_id);
|
||||
// def.def.add_action(unique_id, def.state.c_str(), act);
|
||||
// return *this;
|
||||
// }
|
||||
|
||||
lexer_def_& def;
|
||||
};
|
||||
friend struct adder;
|
||||
|
||||
// allow to use lexer.self.add_pattern("pattern1", "regex1")(...);
|
||||
// syntax
|
||||
struct pattern_adder
|
||||
{
|
||||
pattern_adder(lexer_def_& def_)
|
||||
: def(def_) {}
|
||||
|
||||
pattern_adder const& operator()(string_type const& p
|
||||
, string_type const& s) const
|
||||
{
|
||||
def.def.add_pattern (def.state.c_str(), p, s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
lexer_def_& def;
|
||||
};
|
||||
friend struct pattern_adder;
|
||||
|
||||
private:
|
||||
// Helper function to invoke the necessary 2 step compilation
|
||||
// process on token definition expressions
|
||||
template <typename TokenExpr>
|
||||
void compile2pass(TokenExpr const& expr)
|
||||
{
|
||||
expr.collect(def, state, targetstate);
|
||||
expr.add_actions(def);
|
||||
}
|
||||
|
||||
public:
|
||||
///////////////////////////////////////////////////////////////////
|
||||
template <typename Expr>
|
||||
void define(Expr const& expr)
|
||||
{
|
||||
compile2pass(compile<lex::domain>(expr));
|
||||
}
|
||||
|
||||
lexer_def_(LexerDef& def_, string_type const& state_
|
||||
, string_type const& targetstate_ = string_type())
|
||||
: proto_base_type(terminal_type::make(alias()))
|
||||
, add(this_()), add_pattern(this_()), def(def_)
|
||||
, state(state_), targetstate(targetstate_)
|
||||
{}
|
||||
|
||||
// allow to switch states
|
||||
lexer_def_ operator()(char_type const* state_) const
|
||||
{
|
||||
return lexer_def_(def, state_);
|
||||
}
|
||||
lexer_def_ operator()(char_type const* state_
|
||||
, char_type const* targetstate_) const
|
||||
{
|
||||
return lexer_def_(def, state_, targetstate_);
|
||||
}
|
||||
lexer_def_ operator()(string_type const& state_
|
||||
, string_type const& targetstate_ = string_type()) const
|
||||
{
|
||||
return lexer_def_(def, state_, targetstate_);
|
||||
}
|
||||
|
||||
// allow to assign a token definition expression
|
||||
template <typename Expr>
|
||||
lexer_def_& operator= (Expr const& xpr)
|
||||
{
|
||||
// Report invalid expression error as early as possible.
|
||||
// If you got an error_invalid_expression error message here,
|
||||
// then the expression (expr) is not a valid spirit lex
|
||||
// expression.
|
||||
BOOST_SPIRIT_ASSERT_MATCH(lex::domain, Expr);
|
||||
|
||||
def.clear(state.c_str());
|
||||
define(xpr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// explicitly tell the lexer that the given state will be defined
|
||||
// (useful in conjunction with "*")
|
||||
std::size_t add_state(char_type const* state_ = 0)
|
||||
{
|
||||
return def.add_state(state_ ? state_ : def.initial_state().c_str());
|
||||
}
|
||||
|
||||
adder add;
|
||||
pattern_adder add_pattern;
|
||||
|
||||
private:
|
||||
LexerDef& def;
|
||||
string_type state;
|
||||
string_type targetstate;
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
// allow to assign a token definition expression
|
||||
template <typename LexerDef, typename Expr>
|
||||
inline lexer_def_<LexerDef>&
|
||||
operator+= (lexer_def_<LexerDef>& lexdef, Expr& xpr)
|
||||
{
|
||||
// Report invalid expression error as early as possible.
|
||||
// If you got an error_invalid_expression error message here,
|
||||
// then the expression (expr) is not a valid spirit lex
|
||||
// expression.
|
||||
BOOST_SPIRIT_ASSERT_MATCH(lex::domain, Expr);
|
||||
|
||||
lexdef.define(xpr);
|
||||
return lexdef;
|
||||
}
|
||||
#else
|
||||
// allow to assign a token definition expression
|
||||
template <typename LexerDef, typename Expr>
|
||||
inline lexer_def_<LexerDef>&
|
||||
operator+= (lexer_def_<LexerDef>& lexdef, Expr&& xpr)
|
||||
{
|
||||
// Report invalid expression error as early as possible.
|
||||
// If you got an error_invalid_expression error message here,
|
||||
// then the expression (expr) is not a valid spirit lex
|
||||
// expression.
|
||||
BOOST_SPIRIT_ASSERT_MATCH(lex::domain, Expr);
|
||||
|
||||
lexdef.define(xpr);
|
||||
return lexdef;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename LexerDef, typename Expr>
|
||||
inline lexer_def_<LexerDef>&
|
||||
operator+= (lexer_def_<LexerDef>& lexdef, Expr const& xpr)
|
||||
{
|
||||
// Report invalid expression error as early as possible.
|
||||
// If you got an error_invalid_expression error message here,
|
||||
// then the expression (expr) is not a valid spirit lex
|
||||
// expression.
|
||||
BOOST_SPIRIT_ASSERT_MATCH(lex::domain, Expr);
|
||||
|
||||
lexdef.define(xpr);
|
||||
return lexdef;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The match_flags flags are used to influence different matching
|
||||
// modes of the lexer
|
||||
struct match_flags
|
||||
{
|
||||
enum enum_type
|
||||
{
|
||||
match_default = 0, // no flags
|
||||
match_not_dot_newline = 1, // the regex '.' doesn't match newlines
|
||||
match_icase = 2 // all matching operations are case insensitive
|
||||
};
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This represents a lexer object
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// This is the first token id automatically assigned by the library
|
||||
// if needed
|
||||
enum tokenids
|
||||
{
|
||||
min_token_id = 0x10000
|
||||
};
|
||||
|
||||
template <typename Lexer>
|
||||
class lexer : public Lexer
|
||||
{
|
||||
private:
|
||||
// avoid warnings about using 'this' in constructor
|
||||
lexer& this_() { return *this; }
|
||||
|
||||
std::size_t next_token_id; // has to be an integral type
|
||||
|
||||
public:
|
||||
typedef Lexer lexer_type;
|
||||
typedef typename Lexer::id_type id_type;
|
||||
typedef typename Lexer::char_type char_type;
|
||||
typedef typename Lexer::iterator_type iterator_type;
|
||||
typedef lexer base_type;
|
||||
|
||||
typedef detail::lexer_def_<lexer> lexer_def;
|
||||
typedef std::basic_string<char_type> string_type;
|
||||
|
||||
// if `id_type` was specified but `first_id` is not provided
|
||||
// the `min_token_id` value may be out of range for `id_type`,
|
||||
// but it will be a problem only if unique ids feature is in use.
|
||||
lexer(unsigned int flags = match_flags::match_default)
|
||||
: lexer_type(flags)
|
||||
, next_token_id(min_token_id)
|
||||
, self(this_(), lexer_type::initial_state())
|
||||
{}
|
||||
|
||||
lexer(unsigned int flags, id_type first_id)
|
||||
: lexer_type(flags)
|
||||
, next_token_id(first_id)
|
||||
, self(this_(), lexer_type::initial_state())
|
||||
{}
|
||||
|
||||
// access iterator interface
|
||||
template <typename Iterator>
|
||||
iterator_type begin(Iterator& first, Iterator const& last
|
||||
, char_type const* initial_state = 0) const
|
||||
{ return this->lexer_type::begin(first, last, initial_state); }
|
||||
iterator_type end() const
|
||||
{ return this->lexer_type::end(); }
|
||||
|
||||
std::size_t map_state(char_type const* state)
|
||||
{ return this->lexer_type::add_state(state); }
|
||||
|
||||
// create a unique token id
|
||||
id_type get_next_id() { return id_type(next_token_id++); }
|
||||
|
||||
lexer_def self; // allow for easy token definition
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user