200 lines
7.3 KiB
C++
Executable File
200 lines
7.3 KiB
C++
Executable File
// Copyright (c) 2001-2008 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_TOKEN_DEF_MAR_13_2007_0145PM)
|
|
#define BOOST_SPIRIT_LEX_TOKEN_DEF_MAR_13_2007_0145PM
|
|
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
|
|
#pragma once // MS compatible compilers support #pragma once
|
|
#endif
|
|
|
|
#include <boost/spirit/home/lex/lexer/lexer_fwd.hpp>
|
|
#include <boost/spirit/home/lex/lexer/terminal_holder.hpp>
|
|
#include <boost/fusion/include/vector.hpp>
|
|
#include <boost/spirit/home/qi/skip.hpp>
|
|
#include <boost/spirit/home/qi/detail/construct.hpp>
|
|
#include <boost/spirit/home/qi/detail/assign_to.hpp>
|
|
#include <boost/mpl/if.hpp>
|
|
#include <boost/detail/iterator.hpp>
|
|
#include <boost/type_traits/is_same.hpp>
|
|
#include <string>
|
|
#include <cstdlib>
|
|
|
|
namespace boost { namespace spirit { namespace lex
|
|
{
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// create a unique token id, note this is not thread safe
|
|
///////////////////////////////////////////////////////////////////////////
|
|
enum tokenids {
|
|
// this is the first token id automatically assigned by the library
|
|
// if needed
|
|
min_token_id = 0x10000
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// The next_id template needs to be specialized for any non-default token
|
|
// id type used by a custom token type. It need to expose a function
|
|
// 'static Idtype get()' returning the next available token id each time
|
|
// it is called.
|
|
template <typename Idtype>
|
|
struct next_id;
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Default specialization for the next_id template returning the next
|
|
// available token id.
|
|
template <>
|
|
struct next_id<std::size_t>
|
|
{
|
|
static std::size_t get()
|
|
{
|
|
static std::size_t next_token_id = min_token_id;
|
|
return next_token_id++;
|
|
}
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// This component represents a token definition
|
|
///////////////////////////////////////////////////////////////////////////
|
|
template<typename Attribute, typename Char, typename Idtype>
|
|
class token_def
|
|
: public proto::extends<
|
|
typename make_terminal_holder<
|
|
token_def<Attribute, Char, Idtype>*,
|
|
token_def<Attribute, Char, Idtype>
|
|
>::type,
|
|
token_def<Attribute, Char, Idtype>
|
|
>
|
|
{
|
|
private:
|
|
// initialize proto base class
|
|
typedef terminal_holder<token_def*, token_def> terminal_holder_;
|
|
typedef typename proto::terminal<terminal_holder_>::type tag;
|
|
typedef proto::extends<tag, token_def> base_type;
|
|
|
|
tag make_tag()
|
|
{
|
|
tag xpr = {{ this }};
|
|
return xpr;
|
|
}
|
|
|
|
public:
|
|
// Qi interface: metafunction calculating parser return type
|
|
template <typename Component, typename Context, typename Iterator>
|
|
struct attribute
|
|
{
|
|
// The return value of the token_def is either the specified
|
|
// attribute type, or the pair of iterators from the match of the
|
|
// corresponding token (if no attribute type has been specified),
|
|
// or unused_type (if omitted has been specified).
|
|
typedef typename Iterator::base_iterator_type iterator_type;
|
|
typedef typename
|
|
mpl::if_<
|
|
is_same<Attribute, unused_type>,
|
|
iterator_range<iterator_type>,
|
|
typename mpl::if_<
|
|
is_same<Attribute, omitted>,
|
|
unused_type,
|
|
Attribute
|
|
>::type
|
|
>::type
|
|
type;
|
|
};
|
|
|
|
private:
|
|
// Qi interface: parse functionality
|
|
template <typename Iterator, typename Context, typename Skipper,
|
|
typename Attribute1>
|
|
bool parse(Iterator& first, Iterator const& last,
|
|
Context& /*context*/, Skipper const& skipper, Attribute1& attr) const
|
|
{
|
|
qi::skip(first, last, skipper); // always do a pre-skip
|
|
|
|
if (first != last) {
|
|
typedef typename
|
|
boost::detail::iterator_traits<Iterator>::value_type
|
|
token_type;
|
|
|
|
// If the following assertion fires you probably forgot to
|
|
// associate this token definition with a lexer instance.
|
|
BOOST_ASSERT((std::size_t)(~0) != token_state);
|
|
|
|
token_type &t = *first;
|
|
if (token_id == t.id() && token_state == t.state()) {
|
|
qi::detail::assign_to(t, attr);
|
|
++first;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
friend struct terminal_director;
|
|
|
|
std::string what() const
|
|
{
|
|
std::string result = "token_def(\"";
|
|
result += def;
|
|
result += "\")";
|
|
return result;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// Lex interface: collect token definitions and put it into the
|
|
// provided lexer def
|
|
template <typename LexerDef, typename String>
|
|
void collect(LexerDef& lexdef, String const& state)
|
|
{
|
|
token_state = lexdef.add_state(state.c_str());
|
|
if (0 == token_id)
|
|
token_id = next_id<Idtype>::get();
|
|
lexdef.add_token (state.c_str(), def, token_id);
|
|
}
|
|
|
|
public:
|
|
typedef Char char_type;
|
|
typedef Idtype id_type;
|
|
typedef std::basic_string<char_type> string_type;
|
|
|
|
// Lex interface: constructing token definitions
|
|
token_def()
|
|
: base_type(make_tag()), token_id(0), token_state(~0)
|
|
{}
|
|
explicit token_def(char_type def_, Idtype id_ = Idtype())
|
|
: base_type(make_tag()), def(lex::detail::escape(def_)),
|
|
token_id(0 == id_ ? def_ : id_), token_state(~0)
|
|
{}
|
|
explicit token_def(string_type def_, Idtype id_ = Idtype())
|
|
: base_type(make_tag()), def(def_), token_id(id_), token_state(~0)
|
|
{}
|
|
|
|
template <typename String>
|
|
token_def& operator= (String const& definition)
|
|
{
|
|
def = definition;
|
|
token_id = 0;
|
|
return *this;
|
|
}
|
|
token_def& operator= (token_def const& rhs)
|
|
{
|
|
def = rhs.def;
|
|
token_id = rhs.token_id;
|
|
return *this;
|
|
}
|
|
|
|
// general accessors
|
|
Idtype id() const { return token_id; }
|
|
void id(Idtype id) { token_id = id; }
|
|
string_type const& definition() const { return def; }
|
|
std::size_t state() const { return token_state; }
|
|
|
|
private:
|
|
string_type def;
|
|
Idtype token_id;
|
|
std::size_t token_state;
|
|
};
|
|
|
|
}}}
|
|
|
|
#endif
|