stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork

This commit is contained in:
2026-02-24 18:38:47 +00:00
parent da8c28aaeb
commit 65cb2619a7
13106 changed files with 2484322 additions and 1804 deletions
@@ -0,0 +1,265 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
// Copyright (c) 2010 Bryce Lelbach
// Copyright (c) 2011 Thomas Heller
//
// 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_ARGUMENT_JUNE_07_2009_1106AM)
#define BOOST_SPIRIT_LEX_ARGUMENT_JUNE_07_2009_1106AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/lex/argument_phoenix.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
// The state_getter is a Phoenix actor used to access the name of the
// current lexer state by calling get_state_name() on the context (which
// is the 5th parameter to any lexer semantic actions).
//
// This Phoenix actor is invoked whenever the placeholder '_state' is used
// as a rvalue inside a lexer semantic action:
//
// lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
// this->self = identifier [ std::cout << _state ];
//
// The example shows how to print the lexer state after matching a token
// 'identifier'.
struct state_getter
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef
typename remove_reference<
typename remove_const<
typename mpl::at_c<typename Env::args_type, 4>::type
>::type
>::type
context_type;
typedef typename context_type::state_name_type type;
};
template <typename Env>
typename result<Env>::type
eval(Env const& env) const
{
return fusion::at_c<4>(env.args()).get_state_name();
}
};
///////////////////////////////////////////////////////////////////////////
// The state_setter is a Phoenix actor used to change the name of the
// current lexer state by calling set_state_name() on the context (which
// is the 5th parameter to any lexer semantic actions).
//
// This Phoenix actor is invoked whenever the placeholder '_state' is used
// as a lvalue inside a lexer semantic action:
//
// lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
// this->self = identifier [ _state = "SOME_LEXER_STATE" ];
//
// The example shows how to change the lexer state after matching a token
// 'identifier'.
template <typename Actor>
struct state_setter
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef void type;
};
template <typename Env>
void eval(Env const& env) const
{
fusion::at_c<4>(env.args()).set_state_name(
traits::get_c_string(actor_.eval(env)));
}
state_setter(Actor const& actor)
: actor_(actor) {}
Actor actor_;
};
///////////////////////////////////////////////////////////////////////////
// The value_getter is used to create the _val placeholder, which is a
// Phoenix actor used to access the value of the current token.
//
// This Phoenix actor is invoked whenever the placeholder '_val' is used
// as a rvalue inside a lexer semantic action:
//
// lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
// this->self = identifier [ std::cout << _val ];
//
// The example shows how to use _val to print the identifier name (which
// is the initial token value).
struct value_getter
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef
typename remove_reference<
typename remove_const<
typename mpl::at_c<typename Env::args_type, 4>::type
>::type
>::type
context_type;
typedef typename context_type::get_value_type type;
};
template <typename Env>
typename result<Env>::type
eval(Env const& env) const
{
return fusion::at_c<4>(env.args()).get_value();
}
};
///////////////////////////////////////////////////////////////////////////
// The value_setter is a Phoenix actor used to change the name of the
// current lexer state by calling set_state_name() on the context (which
// is the 5th parameter to any lexer semantic actions).
//
// This Phoenix actor is invoked whenever the placeholder '_val' is used
// as a lvalue inside a lexer semantic action:
//
// lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
// this->self = identifier [ _val = "identifier" ];
//
// The example shows how to change the token value after matching a token
// 'identifier'.
template <typename Actor>
struct value_setter
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef void type;
};
template <typename Env>
void eval(Env const& env) const
{
fusion::at_c<4>(env.args()).set_value(actor_.eval(env));
}
value_setter(Actor const& actor)
: actor_(actor) {}
Actor actor_;
};
///////////////////////////////////////////////////////////////////////////
// The eoi_getter is used to create the _eoi placeholder, which is a
// Phoenix actor used to access the end of input iterator pointing to the
// end of the underlying input sequence.
//
// This actor is invoked whenever the placeholder '_eoi' is used in a
// lexer semantic action:
//
// lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
// this->self = identifier
// [ std::cout << construct_<std::string>(_end, _eoi) ];
//
// The example shows how to use _eoi to print all remaining input after
// matching a token 'identifier'.
struct eoi_getter
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef
typename remove_reference<
typename remove_const<
typename mpl::at_c<typename Env::args_type, 4>::type
>::type
>::type
context_type;
typedef typename context_type::base_iterator_type const& type;
};
template <typename Env>
typename result<Env>::type
eval(Env const& env) const
{
return fusion::at_c<4>(env.args()).get_eoi();
}
};
///////////////////////////////////////////////////////////////////////////
// '_start' and '_end' may be used to access the start and the end of
// the matched sequence of the current token
typedef phoenix::arg_names::_1_type _start_type;
typedef phoenix::arg_names::_2_type _end_type;
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
_start_type const _start = _start_type();
_end_type const _end = _end_type();
#endif
// We are reusing the placeholder '_pass' to access and change the pass
// status of the current match (see support/argument.hpp for its
// definition).
// typedef phoenix::arg_names::_3_type _pass_type;
using boost::spirit::_pass_type;
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using boost::spirit::_pass;
#endif
// '_tokenid' may be used to access and change the tokenid of the current
// token
typedef phoenix::arg_names::_4_type _tokenid_type;
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
_tokenid_type const _tokenid = _tokenid_type();
#endif
typedef phoenix::actor<value_context> _val_type;
typedef phoenix::actor<state_context> _state_type;
typedef phoenix::actor<eoi_getter> _eoi_type;
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
// '_val' may be used to access and change the token value of the current
// token
_val_type const _val = _val_type();
// _state may be used to access and change the name of the current lexer
// state
_state_type const _state = _state_type();
// '_eoi' may be used to access the end of input iterator of the input
// stream used by the lexer to match tokens from
_eoi_type const _eoi = _eoi_type();
#endif
}}}
#undef SPIRIT_DECLARE_ARG
#endif
@@ -0,0 +1,248 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2011 Thomas Heller
//
// 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_ARGUMENT_PHEONIX_MARCH_25_2011_1841PM)
#define BOOST_SPIRIT_LEX_ARGUMENT_PHEONIX_MARCH_25_2011_1841PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/include/phoenix_core.hpp>
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
// The value_context is used as a noop Phoenix actor to create the
// placeholder '_val' (see below). It is a noop actor because it is used
// as a placeholder only, while it is being converted either to a
// value_getter (if used as a rvalue) or to a value_setter (if used as a
// lvalue). The conversion is achieved by specializing and overloading a
// couple of the Phoenix templates from the Phoenix expression composition
// engine (see the end of this file).
struct value_context
{
typedef mpl::true_ no_nullary;
typedef unused_type result_type;
template <typename Env>
struct result
{
typedef unused_type type;
};
template <typename Env>
unused_type
eval(Env const& env) const
{
return unused;
}
};
// forward declarations
struct value_getter;
template <typename> struct value_setter;
///////////////////////////////////////////////////////////////////////////
// The state_context is used as a noop Phoenix actor to create the
// placeholder '_state' (see below). It is a noop actor because it is used
// as a placeholder only, while it is being converted either to a
// state_getter (if used as a rvalue) or to a state_setter (if used as a
// lvalue). The conversion is achieved by specializing and overloading a
// couple of the Phoenix templates from the Phoenix expression composition
// engine (see the end of this file).
struct state_context
{
typedef mpl::true_ no_nullary;
typedef unused_type result_type;
template <typename Env>
struct result
{
typedef unused_type type;
};
template <typename Env>
unused_type
eval(Env const& env) const
{
return unused;
}
};
// forward declarations
struct state_getter;
template <typename> struct state_setter;
struct eoi_getter;
}}}
///////////////////////////////////////////////////////////////////////////////
BOOST_PHOENIX_DEFINE_EXPRESSION(
(boost)(spirit)(lex)(value_setter)
, (boost::phoenix::meta_grammar)
)
BOOST_PHOENIX_DEFINE_EXPRESSION(
(boost)(spirit)(lex)(state_setter)
, (boost::phoenix::meta_grammar)
)
namespace boost { namespace phoenix
{
namespace result_of
{
template <>
struct is_nullary<custom_terminal<boost::spirit::lex::value_context> >
: mpl::false_
{};
}
template <typename Dummy>
struct is_custom_terminal<boost::spirit::lex::value_context, Dummy>: mpl::true_ {};
template <typename Dummy>
struct custom_terminal<boost::spirit::lex::value_context, Dummy>
: proto::call<
v2_eval(
proto::make<boost::spirit::lex::value_getter()>
, proto::call<functional::env(proto::_state)>
)
>
{};
template <typename Dummy>
struct is_nullary::when<spirit::lex::rule::value_setter, Dummy>
: proto::make<mpl::false_()>
{};
template <typename Dummy>
struct default_actions::when<spirit::lex::rule::value_setter, Dummy>
: proto::call<
v2_eval(
proto::make<
spirit::lex::value_setter<proto::_child0>(
proto::_child0
)
>
, _env
)
>
{};
template <>
struct actor<spirit::lex::value_context>
: boost::phoenix::actor<proto::terminal<spirit::lex::value_context>::type>
{
typedef boost::phoenix::actor<
proto::terminal<spirit::lex::value_context>::type
> base_type;
actor(base_type const & base = base_type())
: base_type(base)
{}
template <typename Expr>
typename spirit::lex::expression::value_setter<
typename phoenix::as_actor<Expr>::type>::type const
operator=(Expr const & expr) const
{
return
spirit::lex::expression::value_setter<
typename phoenix::as_actor<Expr>::type
>::make(phoenix::as_actor<Expr>::convert(expr));
}
};
namespace result_of
{
template <>
struct is_nullary<custom_terminal<boost::spirit::lex::state_context> >
: mpl::false_
{};
}
template <typename Dummy>
struct is_custom_terminal<boost::spirit::lex::state_context, Dummy>: mpl::true_ {};
template <typename Dummy>
struct custom_terminal<boost::spirit::lex::state_context, Dummy>
: proto::call<
v2_eval(
proto::make<boost::spirit::lex::state_getter()>
, proto::call<functional::env(proto::_state)>
)
>
{};
template <typename Dummy>
struct is_nullary::when<spirit::lex::rule::state_setter, Dummy>
: proto::make<mpl::false_()>
{};
template <typename Dummy>
struct default_actions::when<spirit::lex::rule::state_setter, Dummy>
: proto::call<
v2_eval(
proto::make<
spirit::lex::state_setter<proto::_child0>(
proto::_child0
)
>
, _env
)
>
{};
template <>
struct actor<spirit::lex::state_context>
: boost::phoenix::actor<proto::terminal<spirit::lex::state_context>::type>
{
typedef boost::phoenix::actor<
proto::terminal<spirit::lex::state_context>::type
> base_type;
actor(base_type const & base = base_type())
: base_type(base)
{}
template <typename Expr>
typename spirit::lex::expression::state_setter<
typename phoenix::as_actor<Expr>::type>::type const
operator=(Expr const & expr) const
{
return
spirit::lex::expression::state_setter<
typename phoenix::as_actor<Expr>::type
>::make(phoenix::as_actor<Expr>::convert(expr));
}
};
namespace result_of
{
template <>
struct is_nullary<custom_terminal<boost::spirit::lex::eoi_getter> >
: mpl::false_
{};
}
template <typename Dummy>
struct is_custom_terminal<boost::spirit::lex::eoi_getter, Dummy>: mpl::true_ {};
template <typename Dummy>
struct custom_terminal<boost::spirit::lex::eoi_getter, Dummy>
: proto::call<
v2_eval(
proto::make<boost::spirit::lex::eoi_getter()>
, proto::call<functional::env(proto::_state)>
)
>
{};
}}
#endif
@@ -0,0 +1,63 @@
// 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_SEQUENCE_FUNCTION_FEB_28_2007_0249PM)
#define BOOST_SPIRIT_LEX_SEQUENCE_FUNCTION_FEB_28_2007_0249PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/domain.hpp>
#include <boost/spirit/home/support/unused.hpp>
namespace boost { namespace spirit { namespace lex { namespace detail
{
template <typename LexerDef, typename String>
struct sequence_collect_function
{
sequence_collect_function(LexerDef& def_, String const& state_
, String const& targetstate_)
: def(def_), state(state_), targetstate(targetstate_) {}
template <typename Component>
bool operator()(Component const& component) const
{
component.collect(def, state, targetstate);
return false; // execute for all sequence elements
}
LexerDef& def;
String const& state;
String const& targetstate;
private:
// silence MSVC warning C4512: assignment operator could not be generated
sequence_collect_function& operator= (sequence_collect_function const&);
};
template <typename LexerDef>
struct sequence_add_actions_function
{
sequence_add_actions_function(LexerDef& def_)
: def(def_) {}
template <typename Component>
bool operator()(Component const& component) const
{
component.add_actions(def);
return false; // execute for all sequence elements
}
LexerDef& def;
private:
// silence MSVC warning C4512: assignment operator could not be generated
sequence_add_actions_function& operator= (sequence_add_actions_function const&);
};
}}}}
#endif
@@ -0,0 +1,31 @@
// Copyright (c) 2001-2011 Joel de Guzman
// 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_DOMAIN_MAR_13_2007_0140PM)
#define BOOST_SPIRIT_LEX_DOMAIN_MAR_13_2007_0140PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/meta_compiler.hpp>
#include <boost/spirit/home/support/info.hpp>
namespace boost { namespace spirit { namespace lex
{
// lex's domain
struct domain {};
// bring in some of spirit parts into spirit::lex
using spirit::unused;
using spirit::unused_type;
using spirit::compile;
using spirit::info;
}}}
#endif
@@ -0,0 +1,21 @@
// 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_LEXER_MAR_22_2007_1008PM)
#define BOOST_SPIRIT_LEXER_MAR_22_2007_1008PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/lexer/terminals.hpp>
#include <boost/spirit/home/lex/lexer/token_def.hpp>
#include <boost/spirit/home/lex/lexer/char_token_def.hpp>
#include <boost/spirit/home/lex/lexer/string_token_def.hpp>
#include <boost/spirit/home/lex/lexer/sequence.hpp>
#include <boost/spirit/home/lex/lexer/action.hpp>
#include <boost/spirit/home/lex/lexer/lexer.hpp>
#endif
@@ -0,0 +1,97 @@
// 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(SPIRIT_LEX_ACTION_NOV_18_2007_0743PM)
#define SPIRIT_LEX_ACTION_NOV_18_2007_0743PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/meta_compiler.hpp>
#include <boost/spirit/home/lex/lexer_type.hpp>
#include <boost/spirit/home/lex/argument.hpp>
#include <boost/spirit/home/lex/lexer/support_functions.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/is_same.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename Action>
struct action : unary_lexer<action<Subject, Action> >
{
action(Subject const& subject, Action f)
: subject(subject), f(f) {}
template <typename LexerDef, typename String>
void collect(LexerDef& lexdef, String const& state
, String const& targetstate) const
{
// collect the token definition information for the token_def
// this action is attached to
subject.collect(lexdef, state, targetstate);
}
template <typename LexerDef>
void add_actions(LexerDef& lexdef) const
{
// call to add all actions attached further down the hierarchy
subject.add_actions(lexdef);
// retrieve the id of the associated token_def and register the
// given semantic action with the lexer instance
lexdef.add_action(subject.unique_id(), subject.state(), f);
}
Subject subject;
Action f;
private:
// silence MSVC warning C4512: assignment operator could not be generated
action& operator= (action const&);
};
}}}
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Karma action meta-compiler
template <>
struct make_component<lex::domain, tag::action>
{
template <typename Sig>
struct result;
template <typename This, typename Elements, typename Modifiers>
struct result<This(Elements, Modifiers)>
{
typedef typename
remove_const<typename Elements::car_type>::type
subject_type;
typedef typename
remove_const<typename Elements::cdr_type::car_type>::type
action_type;
typedef lex::action<subject_type, action_type> type;
};
template <typename Elements>
typename result<make_component(Elements, unused_type)>::type
operator()(Elements const& elements, unused_type) const
{
typename result<make_component(Elements, unused_type)>::type
result(elements.car, elements.cdr.car);
return result;
}
};
}}
#endif
@@ -0,0 +1,242 @@
// 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_CHAR_TOKEN_DEF_MAR_28_2007_0626PM)
#define BOOST_SPIRIT_LEX_CHAR_TOKEN_DEF_MAR_28_2007_0626PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/lex/domain.hpp>
#include <boost/spirit/home/lex/lexer_type.hpp>
#include <boost/spirit/home/lex/meta_compiler.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables 'x'
template <>
struct use_terminal<lex::domain, char>
: mpl::true_ {};
// enables "x"
template <>
struct use_terminal<lex::domain, char[2]>
: mpl::true_ {};
// enables wchar_t
template <>
struct use_terminal<lex::domain, wchar_t>
: mpl::true_ {};
// enables L"x"
template <>
struct use_terminal<lex::domain, wchar_t[2]>
: mpl::true_ {};
// enables char_('x'), char_("x")
template <typename CharEncoding, typename A0>
struct use_terminal<lex::domain
, terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector1<A0> > >
: mpl::true_ {};
// enables char_('x', ID), char_("x", ID)
template <typename CharEncoding, typename A0, typename A1>
struct use_terminal<lex::domain
, terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector2<A0, A1> > >
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace lex
{
// use char_ from standard character set by default
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::standard::char_;
#endif
using spirit::standard::char_type;
///////////////////////////////////////////////////////////////////////////
//
// char_token_def
// represents a single character token definition
//
///////////////////////////////////////////////////////////////////////////
template <typename CharEncoding = char_encoding::standard
, typename IdType = std::size_t>
struct char_token_def
: primitive_lexer<char_token_def<CharEncoding, IdType> >
{
typedef typename CharEncoding::char_type char_type;
char_token_def(char_type ch, IdType const& id)
: ch(ch), id_(id), unique_id_(std::size_t(~0))
, token_state_(std::size_t(~0))
{}
template <typename LexerDef, typename String>
void collect(LexerDef& lexdef, String const& state
, String const& targetstate) const
{
std::size_t state_id = lexdef.add_state(state.c_str());
// If the following assertion fires you are probably trying to use
// a single char_token_def instance in more than one lexer state.
// This is not possible. Please create a separate token_def instance
// from the same regular expression for each lexer state it needs
// to be associated with.
BOOST_ASSERT(
(std::size_t(~0) == token_state_ || state_id == token_state_) &&
"Can't use single char_token_def with more than one lexer state");
char_type const* target = targetstate.empty() ? 0 : targetstate.c_str();
if (target)
lexdef.add_state(target);
token_state_ = state_id;
unique_id_ = lexdef.add_token (state.c_str(), ch, id_, target);
}
template <typename LexerDef>
void add_actions(LexerDef&) const {}
IdType id() const { return id_; }
std::size_t unique_id() const { return unique_id_; }
std::size_t state() const { return token_state_; }
char_type ch;
mutable IdType id_;
mutable std::size_t unique_id_;
mutable std::size_t token_state_;
};
///////////////////////////////////////////////////////////////////////////
// Lexer generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename CharEncoding>
struct basic_literal
{
typedef char_token_def<CharEncoding> result_type;
template <typename Char>
result_type operator()(Char ch, unused_type) const
{
return result_type(ch, ch);
}
template <typename Char>
result_type operator()(Char const* str, unused_type) const
{
return result_type(str[0], str[0]);
}
};
}
// literals: 'x', "x"
template <typename Modifiers>
struct make_primitive<char, Modifiers>
: detail::basic_literal<char_encoding::standard> {};
template <typename Modifiers>
struct make_primitive<char const(&)[2], Modifiers>
: detail::basic_literal<char_encoding::standard> {};
// literals: L'x', L"x"
template <typename Modifiers>
struct make_primitive<wchar_t, Modifiers>
: detail::basic_literal<char_encoding::standard_wide> {};
template <typename Modifiers>
struct make_primitive<wchar_t const(&)[2], Modifiers>
: detail::basic_literal<char_encoding::standard_wide> {};
// handle char_('x')
template <typename CharEncoding, typename Modifiers, typename A0>
struct make_primitive<
terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector1<A0>
>
, Modifiers>
{
typedef char_token_def<CharEncoding> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args), fusion::at_c<0>(term.args));
}
};
// handle char_("x")
template <typename CharEncoding, typename Modifiers, typename Char>
struct make_primitive<
terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector1<Char(&)[2]> // single char strings
>
, Modifiers>
{
typedef char_token_def<CharEncoding> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
Char ch = fusion::at_c<0>(term.args)[0];
return result_type(ch, ch);
}
};
// handle char_('x', ID)
template <typename CharEncoding, typename Modifiers, typename A0, typename A1>
struct make_primitive<
terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector2<A0, A1>
>
, Modifiers>
{
typedef char_token_def<CharEncoding> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(
fusion::at_c<0>(term.args), fusion::at_c<1>(term.args));
}
};
// handle char_("x", ID)
template <typename CharEncoding, typename Modifiers, typename Char, typename A1>
struct make_primitive<
terminal_ex<
tag::char_code<tag::char_, CharEncoding>
, fusion::vector2<Char(&)[2], A1> // single char strings
>
, Modifiers>
{
typedef char_token_def<CharEncoding> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(
fusion::at_c<0>(term.args)[0], fusion::at_c<1>(term.args));
}
};
}}} // namespace boost::spirit::lex
#endif
@@ -0,0 +1,405 @@
// 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/detail/iterator.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/range/iterator_range.hpp>
#include <string>
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
namespace detail
{
///////////////////////////////////////////////////////////////////////
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
boost::detail::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;
private:
// silence MSVC warning C4512: assignment operator could not be generated
adder& operator= (adder const&);
};
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;
private:
// silence MSVC warning C4512: assignment operator could not be generated
pattern_adder& operator= (pattern_adder const&);
};
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;
private:
// silence MSVC warning C4512: assignment operator could not be generated
lexer_def_& operator= (lexer_def_ const&);
};
#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;
lexer(unsigned int flags = match_flags::match_default
, id_type first_id = id_type(min_token_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
@@ -0,0 +1,300 @@
// 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_FUNCTOR_NOV_18_2007_1112PM)
#define BOOST_SPIRIT_LEX_LEXER_FUNCTOR_NOV_18_2007_1112PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/bool.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/spirit/home/lex/lexer/pass_flags.hpp>
#include <boost/assert.hpp>
#if 0 != __COMO_VERSION__ || !BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
#define BOOST_SPIRIT_STATIC_EOF 1
#define BOOST_SPIRIT_EOF_PREFIX static
#else
#define BOOST_SPIRIT_EOF_PREFIX
#endif
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
///////////////////////////////////////////////////////////////////////////
//
// functor is a template usable as the functor object for the
// multi_pass iterator allowing to wrap a lexertl based dfa into a
// iterator based interface.
//
// Token: the type of the tokens produced by this functor
// this needs to expose a constructor with the following
// prototype:
//
// Token(std::size_t id, std::size_t state,
// Iterator start, Iterator end)
//
// where 'id' is the token id, state is the lexer state,
// this token has been matched in, and 'first' and 'end'
// mark the start and the end of the token with respect
// to the underlying character stream.
// FunctorData:
// this is expected to encapsulate the shared part of the
// functor (see lex/lexer/lexertl/functor_data.hpp for an
// example and documentation).
// Iterator: the type of the underlying iterator
// SupportsActors:
// this is expected to be a mpl::bool_, if mpl::true_ the
// functor invokes functors which (optionally) have
// been attached to the token definitions.
// SupportState:
// this is expected to be a mpl::bool_, if mpl::true_ the
// functor supports different lexer states,
// otherwise no lexer state is supported.
//
///////////////////////////////////////////////////////////////////////////
template <typename Token
, template <typename, typename, typename, typename> class FunctorData
, typename Iterator = typename Token::iterator_type
, typename SupportsActors = mpl::false_
, typename SupportsState = typename Token::has_state>
class functor
{
public:
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
char_type;
private:
// Needed by compilers not implementing the resolution to DR45. For
// reference, see
// http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#45.
typedef typename Token::token_value_type token_value_type;
friend class FunctorData<Iterator, SupportsActors, SupportsState
, token_value_type>;
// Helper template allowing to assign a value on exit
template <typename T>
struct assign_on_exit
{
assign_on_exit(T& dst, T const& src)
: dst_(dst), src_(src) {}
~assign_on_exit()
{
dst_ = src_;
}
T& dst_;
T const& src_;
private:
// silence MSVC warning C4512: assignment operator could not be generated
assign_on_exit& operator= (assign_on_exit const&);
};
public:
functor()
#if defined(__PGI)
: eof()
#endif
{}
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
// somehow VC7.1 needs this (meaningless) assignment operator
functor& operator=(functor const& rhs)
{
return *this;
}
#endif
///////////////////////////////////////////////////////////////////////
// interface to the iterator_policies::split_functor_input policy
typedef Token result_type;
typedef functor unique;
typedef FunctorData<Iterator, SupportsActors, SupportsState
, token_value_type> shared;
BOOST_SPIRIT_EOF_PREFIX result_type const eof;
///////////////////////////////////////////////////////////////////////
typedef Iterator iterator_type;
typedef typename shared::semantic_actions_type semantic_actions_type;
typedef typename shared::next_token_functor next_token_functor;
typedef typename shared::get_state_name_type get_state_name_type;
// this is needed to wrap the semantic actions in a proper way
typedef typename shared::wrap_action_type wrap_action_type;
///////////////////////////////////////////////////////////////////////
template <typename MultiPass>
static result_type& get_next(MultiPass& mp, result_type& result)
{
typedef typename result_type::id_type id_type;
shared& data = mp.shared()->ftor;
for(;;)
{
if (data.get_first() == data.get_last())
#if defined(BOOST_SPIRIT_STATIC_EOF)
return result = eof;
#else
return result = mp.ftor.eof;
#endif
data.reset_value();
Iterator end = data.get_first();
std::size_t unique_id = boost::lexer::npos;
bool prev_bol = false;
// lexer matching might change state
std::size_t state = data.get_state();
std::size_t id = data.next(end, unique_id, prev_bol);
if (boost::lexer::npos == id) { // no match
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
std::string next;
Iterator it = data.get_first();
for (std::size_t i = 0; i < 10 && it != data.get_last(); ++it, ++i)
next += *it;
std::cerr << "Not matched, in state: " << state
<< ", lookahead: >" << next << "<" << std::endl;
#endif
return result = result_type(0);
}
else if (0 == id) { // EOF reached
#if defined(BOOST_SPIRIT_STATIC_EOF)
return result = eof;
#else
return result = mp.ftor.eof;
#endif
}
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
{
std::string next;
Iterator it = end;
for (std::size_t i = 0; i < 10 && it != data.get_last(); ++it, ++i)
next += *it;
std::cerr << "Matched: " << id << ", in state: "
<< state << ", string: >"
<< std::basic_string<char_type>(data.get_first(), end) << "<"
<< ", lookahead: >" << next << "<" << std::endl;
if (data.get_state() != state) {
std::cerr << "Switched to state: "
<< data.get_state() << std::endl;
}
}
#endif
// account for a possibly pending lex::more(), i.e. moving
// data.first_ back to the start of the previously matched token.
bool adjusted = data.adjust_start();
// set the end of the matched input sequence in the token data
data.set_end(end);
// invoke attached semantic actions, if defined, might change
// state, id, data.first_, and/or end
BOOST_SCOPED_ENUM(pass_flags) pass =
data.invoke_actions(state, id, unique_id, end);
if (data.has_value()) {
// return matched token using the token value as set before
// using data.set_value(), advancing 'data.first_' past the
// matched sequence
assign_on_exit<Iterator> on_exit(data.get_first(), end);
return result = result_type(id_type(id), state, data.get_value());
}
else if (pass_flags::pass_normal == pass) {
// return matched token, advancing 'data.first_' past the
// matched sequence
assign_on_exit<Iterator> on_exit(data.get_first(), end);
return result = result_type(id_type(id), state, data.get_first(), end);
}
else if (pass_flags::pass_fail == pass) {
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
std::cerr << "Matching forced to fail" << std::endl;
#endif
// if the data.first_ got adjusted above, revert this adjustment
if (adjusted)
data.revert_adjust_start();
// one of the semantic actions signaled no-match
data.reset_bol(prev_bol);
if (state != data.get_state())
continue; // retry matching if state has changed
// if the state is unchanged repeating the match wouldn't
// move the input forward, causing an infinite loop
return result = result_type(0);
}
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
std::cerr << "Token ignored, continuing matching" << std::endl;
#endif
// if this token needs to be ignored, just repeat the matching,
// while starting right after the current match
data.get_first() = end;
}
}
// set_state are propagated up to the iterator interface, allowing to
// manipulate the current lexer state through any of the exposed
// iterators.
template <typename MultiPass>
static std::size_t set_state(MultiPass& mp, std::size_t state)
{
std::size_t oldstate = mp.shared()->ftor.get_state();
mp.shared()->ftor.set_state(state);
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
std::cerr << "Switching state from: " << oldstate
<< " to: " << state
<< std::endl;
#endif
return oldstate;
}
template <typename MultiPass>
static std::size_t get_state(MultiPass& mp)
{
return mp.shared()->ftor.get_state();
}
template <typename MultiPass>
static std::size_t
map_state(MultiPass const& mp, char_type const* statename)
{
return mp.shared()->ftor.get_state_id(statename);
}
// we don't need this, but it must be there
template <typename MultiPass>
static void destroy(MultiPass const&) {}
};
#if defined(BOOST_SPIRIT_STATIC_EOF)
///////////////////////////////////////////////////////////////////////////
// eof token
///////////////////////////////////////////////////////////////////////////
template <typename Token
, template <typename, typename, typename, typename> class FunctorData
, typename Iterator, typename SupportsActors, typename SupportsState>
typename functor<Token, FunctorData, Iterator, SupportsActors, SupportsState>::result_type const
functor<Token, FunctorData, Iterator, SupportsActors, SupportsState>::eof =
typename functor<Token, FunctorData, Iterator, SupportsActors
, SupportsState>::result_type();
#endif
}}}}
#undef BOOST_SPIRIT_EOF_PREFIX
#undef BOOST_SPIRIT_STATIC_EOF
#endif
@@ -0,0 +1,552 @@
// 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_FUNCTOR_DATA_JUN_10_2009_0954AM)
#define BOOST_SPIRIT_LEX_LEXER_FUNCTOR_DATA_JUN_10_2009_0954AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/qi/detail/assign_to.hpp>
#include <boost/spirit/home/support/detail/lexer/generator.hpp>
#include <boost/spirit/home/support/detail/lexer/rules.hpp>
#include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/iterator_tokenizer.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/semantic_action_data.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/wrap_action.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/optional.hpp>
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
namespace detail
{
///////////////////////////////////////////////////////////////////////
template <typename Iterator, typename HasActors, typename HasState
, typename TokenValue>
class data; // no default specialization
///////////////////////////////////////////////////////////////////////
// neither supports state, nor actors
template <typename Iterator, typename TokenValue>
class data<Iterator, mpl::false_, mpl::false_, TokenValue>
{
protected:
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
char_type;
public:
typedef Iterator base_iterator_type;
typedef iterator_range<Iterator> token_value_type;
typedef token_value_type get_value_type;
typedef std::size_t state_type;
typedef char_type const* state_name_type;
typedef unused_type semantic_actions_type;
typedef detail::wrap_action<unused_type, Iterator, data, std::size_t>
wrap_action_type;
typedef unused_type next_token_functor;
typedef unused_type get_state_name_type;
// initialize the shared data
template <typename IterData>
data (IterData const& data_, Iterator& first, Iterator const& last)
: first_(first), last_(last)
, state_machine_(data_.state_machine_)
, rules_(data_.rules_)
, bol_(data_.state_machine_.data()._seen_BOL_assertion) {}
// The following functions are used by the implementation of the
// placeholder '_state'.
template <typename Char>
void set_state_name (Char const*)
{
// some (random) versions of gcc instantiate this function even if it's not
// needed leading to false static asserts
#if !defined(__GNUC__)
// If you see a compile time assertion below you're probably
// using a token type not supporting lexer states (the 3rd
// template parameter of the token is mpl::false_), but your
// code uses state changes anyways.
BOOST_STATIC_ASSERT(false);
#endif
}
char_type const* get_state_name() const { return rules_.initial(); }
std::size_t get_state_id (char_type const*) const
{
return 0;
}
// The function get_eoi() is used by the implementation of the
// placeholder '_eoi'.
Iterator const& get_eoi() const { return last_; }
// The function less() is used by the implementation of the support
// function lex::less(). Its functionality is equivalent to flex'
// function yyless(): it returns an iterator positioned to the
// nth input character beyond the current start iterator (i.e. by
// assigning the return value to the placeholder '_end' it is
// possible to return all but the first n characters of the current
// token back to the input stream.
//
// This function does nothing as long as no semantic actions are
// used.
Iterator const& less(Iterator const& it, int)
{
// The following assertion fires most likely because you are
// using lexer semantic actions without using the actor_lexer
// as the base class for your token definition class.
BOOST_ASSERT(false &&
"Are you using lexer semantic actions without using the "
"actor_lexer base?");
return it;
}
// The function more() is used by the implementation of the support
// function lex::more(). Its functionality is equivalent to flex'
// function yymore(): it tells the lexer that the next time it
// matches a rule, the corresponding token should be appended onto
// the current token value rather than replacing it.
//
// These functions do nothing as long as no semantic actions are
// used.
void more()
{
// The following assertion fires most likely because you are
// using lexer semantic actions without using the actor_lexer
// as the base class for your token definition class.
BOOST_ASSERT(false &&
"Are you using lexer semantic actions without using the "
"actor_lexer base?");
}
bool adjust_start() { return false; }
void revert_adjust_start() {}
// The function lookahead() is used by the implementation of the
// support function lex::lookahead. It can be used to implement
// lookahead for lexer engines not supporting constructs like flex'
// a/b (match a, but only when followed by b):
//
// This function does nothing as long as no semantic actions are
// used.
bool lookahead(std::size_t, std::size_t /*state*/ = std::size_t(~0))
{
// The following assertion fires most likely because you are
// using lexer semantic actions without using the actor_lexer
// as the base class for your token definition class.
BOOST_ASSERT(false &&
"Are you using lexer semantic actions without using the "
"actor_lexer base?");
return false;
}
// the functions next, invoke_actions, and get_state are used by
// the functor implementation below
// The function next() tries to match the next token from the
// underlying input sequence.
std::size_t next(Iterator& end, std::size_t& unique_id, bool& prev_bol)
{
prev_bol = bol_;
typedef basic_iterator_tokeniser<Iterator> tokenizer;
return tokenizer::next(state_machine_, bol_, end, last_
, unique_id);
}
// nothing to invoke, so this is empty
BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t
, std::size_t, std::size_t, Iterator const&)
{
return pass_flags::pass_normal; // always accept
}
std::size_t get_state() const { return 0; }
void set_state(std::size_t) {}
void set_end(Iterator const& /*it*/) {}
Iterator& get_first() { return first_; }
Iterator const& get_first() const { return first_; }
Iterator const& get_last() const { return last_; }
iterator_range<Iterator> get_value() const
{
return iterator_range<Iterator>(first_, last_);
}
bool has_value() const { return false; }
void reset_value() {}
void reset_bol(bool bol) { bol_ = bol; }
protected:
Iterator& first_;
Iterator last_;
boost::lexer::basic_state_machine<char_type> const& state_machine_;
boost::lexer::basic_rules<char_type> const& rules_;
bool bol_; // helper storing whether last character was \n
private:
// silence MSVC warning C4512: assignment operator could not be generated
data& operator= (data const&);
};
///////////////////////////////////////////////////////////////////////
// doesn't support lexer semantic actions, but supports state
template <typename Iterator, typename TokenValue>
class data<Iterator, mpl::false_, mpl::true_, TokenValue>
: public data<Iterator, mpl::false_, mpl::false_, TokenValue>
{
protected:
typedef data<Iterator, mpl::false_, mpl::false_, TokenValue> base_type;
typedef typename base_type::char_type char_type;
public:
typedef Iterator base_iterator_type;
typedef iterator_range<Iterator> token_value_type;
typedef token_value_type get_value_type;
typedef typename base_type::state_type state_type;
typedef typename base_type::state_name_type state_name_type;
typedef typename base_type::semantic_actions_type
semantic_actions_type;
// initialize the shared data
template <typename IterData>
data (IterData const& data_, Iterator& first, Iterator const& last)
: base_type(data_, first, last)
, state_(0) {}
// The following functions are used by the implementation of the
// placeholder '_state'.
void set_state_name (char_type const* new_state)
{
std::size_t state_id = this->rules_.state(new_state);
// If the following assertion fires you've probably been using
// a lexer state name which was not defined in your token
// definition.
BOOST_ASSERT(state_id != boost::lexer::npos);
if (state_id != boost::lexer::npos)
state_ = state_id;
}
char_type const* get_state_name() const
{
return this->rules_.state(state_);
}
std::size_t get_state_id (char_type const* state) const
{
return this->rules_.state(state);
}
// the functions next() and get_state() are used by the functor
// implementation below
// The function next() tries to match the next token from the
// underlying input sequence.
std::size_t next(Iterator& end, std::size_t& unique_id, bool& prev_bol)
{
prev_bol = this->bol_;
typedef basic_iterator_tokeniser<Iterator> tokenizer;
return tokenizer::next(this->state_machine_, state_,
this->bol_, end, this->get_eoi(), unique_id);
}
std::size_t& get_state() { return state_; }
void set_state(std::size_t state) { state_ = state; }
protected:
std::size_t state_;
private:
// silence MSVC warning C4512: assignment operator could not be generated
data& operator= (data const&);
};
///////////////////////////////////////////////////////////////////////
// does support lexer semantic actions, may support state
template <typename Iterator, typename HasState, typename TokenValue>
class data<Iterator, mpl::true_, HasState, TokenValue>
: public data<Iterator, mpl::false_, HasState, TokenValue>
{
public:
typedef semantic_actions<Iterator, HasState, data>
semantic_actions_type;
protected:
typedef data<Iterator, mpl::false_, HasState, TokenValue> base_type;
typedef typename base_type::char_type char_type;
typedef typename semantic_actions_type::functor_wrapper_type
functor_wrapper_type;
public:
typedef Iterator base_iterator_type;
typedef TokenValue token_value_type;
typedef TokenValue const& get_value_type;
typedef typename base_type::state_type state_type;
typedef typename base_type::state_name_type state_name_type;
typedef detail::wrap_action<functor_wrapper_type
, Iterator, data, std::size_t> wrap_action_type;
template <typename IterData>
data (IterData const& data_, Iterator& first, Iterator const& last)
: base_type(data_, first, last)
, actions_(data_.actions_), hold_()
, value_(iterator_range<Iterator>(last, last))
, has_value_(false), has_hold_(false) {}
// invoke attached semantic actions, if defined
BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t state
, std::size_t& id, std::size_t unique_id, Iterator& end)
{
return actions_.invoke_actions(state, id, unique_id, end, *this);
}
// The function less() is used by the implementation of the support
// function lex::less(). Its functionality is equivalent to flex'
// function yyless(): it returns an iterator positioned to the
// nth input character beyond the current start iterator (i.e. by
// assigning the return value to the placeholder '_end' it is
// possible to return all but the first n characters of the current
// token back to the input stream).
Iterator const& less(Iterator& it, int n)
{
it = this->get_first();
std::advance(it, n);
return it;
}
// The function more() is used by the implementation of the support
// function lex::more(). Its functionality is equivalent to flex'
// function yymore(): it tells the lexer that the next time it
// matches a rule, the corresponding token should be appended onto
// the current token value rather than replacing it.
void more()
{
hold_ = this->get_first();
has_hold_ = true;
}
// The function lookahead() is used by the implementation of the
// support function lex::lookahead. It can be used to implement
// lookahead for lexer engines not supporting constructs like flex'
// a/b (match a, but only when followed by b)
bool lookahead(std::size_t id, std::size_t state = std::size_t(~0))
{
Iterator end = end_;
std::size_t unique_id = boost::lexer::npos;
bool bol = this->bol_;
if (std::size_t(~0) == state)
state = this->state_;
typedef basic_iterator_tokeniser<Iterator> tokenizer;
return id == tokenizer::next(this->state_machine_, state,
bol, end, this->get_eoi(), unique_id);
}
// The adjust_start() and revert_adjust_start() are helper
// functions needed to implement the functionality required for
// lex::more(). It is called from the functor body below.
bool adjust_start()
{
if (!has_hold_)
return false;
std::swap(this->get_first(), hold_);
has_hold_ = false;
return true;
}
void revert_adjust_start()
{
// this will be called only if adjust_start above returned true
std::swap(this->get_first(), hold_);
has_hold_ = true;
}
TokenValue const& get_value() const
{
if (!has_value_) {
value_ = iterator_range<Iterator>(this->get_first(), end_);
has_value_ = true;
}
return value_;
}
template <typename Value>
void set_value(Value const& val)
{
value_ = val;
has_value_ = true;
}
void set_end(Iterator const& it)
{
end_ = it;
}
bool has_value() const { return has_value_; }
void reset_value() { has_value_ = false; }
protected:
semantic_actions_type const& actions_;
Iterator hold_; // iterator needed to support lex::more()
Iterator end_; // iterator pointing to end of matched token
mutable TokenValue value_; // token value to use
mutable bool has_value_; // 'true' if value_ is valid
bool has_hold_; // 'true' if hold_ is valid
private:
// silence MSVC warning C4512: assignment operator could not be generated
data& operator= (data const&);
};
///////////////////////////////////////////////////////////////////////
// does support lexer semantic actions, may support state, is used for
// position_token exposing exactly one type
template <typename Iterator, typename HasState, typename TokenValue>
class data<Iterator, mpl::true_, HasState, boost::optional<TokenValue> >
: public data<Iterator, mpl::false_, HasState, TokenValue>
{
public:
typedef semantic_actions<Iterator, HasState, data>
semantic_actions_type;
protected:
typedef data<Iterator, mpl::false_, HasState, TokenValue> base_type;
typedef typename base_type::char_type char_type;
typedef typename semantic_actions_type::functor_wrapper_type
functor_wrapper_type;
public:
typedef Iterator base_iterator_type;
typedef boost::optional<TokenValue> token_value_type;
typedef boost::optional<TokenValue> const& get_value_type;
typedef typename base_type::state_type state_type;
typedef typename base_type::state_name_type state_name_type;
typedef detail::wrap_action<functor_wrapper_type
, Iterator, data, std::size_t> wrap_action_type;
template <typename IterData>
data (IterData const& data_, Iterator& first, Iterator const& last)
: base_type(data_, first, last)
, actions_(data_.actions_), hold_()
, has_value_(false), has_hold_(false)
{
spirit::traits::assign_to(first, last, value_);
has_value_ = true;
}
// invoke attached semantic actions, if defined
BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t state
, std::size_t& id, std::size_t unique_id, Iterator& end)
{
return actions_.invoke_actions(state, id, unique_id, end, *this);
}
// The function less() is used by the implementation of the support
// function lex::less(). Its functionality is equivalent to flex'
// function yyless(): it returns an iterator positioned to the
// nth input character beyond the current start iterator (i.e. by
// assigning the return value to the placeholder '_end' it is
// possible to return all but the first n characters of the current
// token back to the input stream).
Iterator const& less(Iterator& it, int n)
{
it = this->get_first();
std::advance(it, n);
return it;
}
// The function more() is used by the implementation of the support
// function lex::more(). Its functionality is equivalent to flex'
// function yymore(): it tells the lexer that the next time it
// matches a rule, the corresponding token should be appended onto
// the current token value rather than replacing it.
void more()
{
hold_ = this->get_first();
has_hold_ = true;
}
// The function lookahead() is used by the implementation of the
// support function lex::lookahead. It can be used to implement
// lookahead for lexer engines not supporting constructs like flex'
// a/b (match a, but only when followed by b)
bool lookahead(std::size_t id, std::size_t state = std::size_t(~0))
{
Iterator end = end_;
std::size_t unique_id = boost::lexer::npos;
bool bol = this->bol_;
if (std::size_t(~0) == state)
state = this->state_;
typedef basic_iterator_tokeniser<Iterator> tokenizer;
return id == tokenizer::next(this->state_machine_, state,
bol, end, this->get_eoi(), unique_id);
}
// The adjust_start() and revert_adjust_start() are helper
// functions needed to implement the functionality required for
// lex::more(). It is called from the functor body below.
bool adjust_start()
{
if (!has_hold_)
return false;
std::swap(this->get_first(), hold_);
has_hold_ = false;
return true;
}
void revert_adjust_start()
{
// this will be called only if adjust_start above returned true
std::swap(this->get_first(), hold_);
has_hold_ = true;
}
token_value_type const& get_value() const
{
if (!has_value_) {
spirit::traits::assign_to(this->get_first(), end_, value_);
has_value_ = true;
}
return value_;
}
template <typename Value>
void set_value(Value const& val)
{
value_ = val;
has_value_ = true;
}
void set_end(Iterator const& it)
{
end_ = it;
}
bool has_value() const { return has_value_; }
void reset_value() { has_value_ = false; }
protected:
semantic_actions_type const& actions_;
Iterator hold_; // iterator needed to support lex::more()
Iterator end_; // iterator pointing to end of matched token
mutable token_value_type value_; // token value to use
mutable bool has_value_; // 'true' if value_ is valid
bool has_hold_; // 'true' if hold_ is valid
private:
// silence MSVC warning C4512: assignment operator could not be generated
data& operator= (data const&);
};
}
}}}}
#endif
@@ -0,0 +1,149 @@
// 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_ITERATOR_MAR_16_2007_0353PM)
#define BOOST_SPIRIT_LEX_LEXER_ITERATOR_MAR_16_2007_0353PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/multi_pass_wrapper.hpp>
#if defined(BOOST_SPIRIT_DEBUG)
#include <boost/spirit/home/support/iterators/detail/buf_id_check_policy.hpp>
#else
#include <boost/spirit/home/support/iterators/detail/no_check_policy.hpp>
#endif
#include <boost/spirit/home/support/iterators/detail/split_functor_input_policy.hpp>
#include <boost/spirit/home/support/iterators/detail/ref_counted_policy.hpp>
#include <boost/spirit/home/support/iterators/detail/split_std_deque_policy.hpp>
#include <boost/spirit/home/support/iterators/multi_pass.hpp>
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
///////////////////////////////////////////////////////////////////////////
template <typename FunctorData>
struct make_multi_pass
{
// Divide the given functor type into its components (unique and
// shared) and build a std::pair from these parts
typedef std::pair<typename FunctorData::unique
, typename FunctorData::shared> functor_data_type;
// This is the result type returned from the iterator
typedef typename FunctorData::result_type result_type;
// Compose the multi_pass iterator policy type from the appropriate
// policies
typedef iterator_policies::split_functor_input input_policy;
typedef iterator_policies::ref_counted ownership_policy;
#if defined(BOOST_SPIRIT_DEBUG)
typedef iterator_policies::buf_id_check check_policy;
#else
typedef iterator_policies::no_check check_policy;
#endif
typedef iterator_policies::split_std_deque storage_policy;
typedef iterator_policies::default_policy<
ownership_policy, check_policy, input_policy, storage_policy>
policy_type;
// Compose the multi_pass iterator from the policy
typedef spirit::multi_pass<functor_data_type, policy_type> type;
};
///////////////////////////////////////////////////////////////////////////
// lexer_iterator exposes an iterator for a lexertl based dfa (lexer)
// The template parameters have the same semantics as described for the
// functor above.
///////////////////////////////////////////////////////////////////////////
template <typename Functor>
class iterator : public make_multi_pass<Functor>::type
{
public:
typedef typename Functor::unique unique_functor_type;
typedef typename Functor::shared shared_functor_type;
typedef typename Functor::iterator_type base_iterator_type;
typedef typename Functor::result_type token_type;
private:
typedef typename make_multi_pass<Functor>::functor_data_type
functor_type;
typedef typename make_multi_pass<Functor>::type base_type;
typedef typename Functor::char_type char_type;
public:
// create a new iterator encapsulating the lexer object to be used
// for tokenization
template <typename IteratorData>
iterator(IteratorData const& iterdata_, base_iterator_type& first
, base_iterator_type const& last, char_type const* state = 0)
: base_type(functor_type(unique_functor_type()
, shared_functor_type(iterdata_, first, last)))
{
set_state(map_state(state));
}
// create an end iterator usable for end of range checking
iterator() {}
// (wash): < mgaunard> T it; T it2 = ++it; doesn't ocmpile
// < mgaunard> this gets fixed by adding
iterator(const base_type& base)
: base_type(base) { }
// set the new required state for the underlying lexer object
std::size_t set_state(std::size_t state)
{
return unique_functor_type::set_state(*this, state);
}
// get the curent state for the underlying lexer object
std::size_t get_state()
{
return unique_functor_type::get_state(*this);
}
// map the given state name to a corresponding state id as understood
// by the underlying lexer object
std::size_t map_state(char_type const* statename)
{
return (0 != statename)
? unique_functor_type::map_state(*this, statename)
: 0;
}
};
}}
namespace traits
{
template <typename Functor>
struct is_multi_pass<spirit::lex::lexertl::iterator<Functor> >
: mpl::true_ {};
template <typename Functor>
void clear_queue(spirit::lex::lexertl::iterator<Functor> & mp
, BOOST_SCOPED_ENUM(traits::clear_mode) mode)
{
mp.clear_queue(mode);
}
template <typename Functor>
void inhibit_clear_queue(spirit::lex::lexertl::iterator<Functor>& mp, bool flag)
{
mp.inhibit_clear_queue(flag);
}
template <typename Functor>
bool inhibit_clear_queue(spirit::lex::lexertl::iterator<Functor>& mp)
{
return mp.inhibit_clear_queue();
}
}
}}
#endif
@@ -0,0 +1,255 @@
// 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_LEXERTL_ITERATOR_TOKENISER_MARCH_22_2007_0859AM)
#define BOOST_SPIRIT_LEXERTL_ITERATOR_TOKENISER_MARCH_22_2007_0859AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/detail/iterator.hpp>
#include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
#include <boost/spirit/home/support/detail/lexer/consts.hpp>
#include <boost/spirit/home/support/detail/lexer/size_t.hpp>
#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
#include <vector>
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
///////////////////////////////////////////////////////////////////////////
template<typename Iterator>
class basic_iterator_tokeniser
{
public:
typedef std::vector<std::size_t> size_t_vector;
typedef typename boost::detail::iterator_traits<Iterator>::value_type
char_type;
static std::size_t next (
boost::lexer::basic_state_machine<char_type> const& state_machine_
, std::size_t &dfa_state_, bool& bol_, Iterator &start_token_
, Iterator const& end_, std::size_t& unique_id_)
{
if (start_token_ == end_)
{
unique_id_ = boost::lexer::npos;
return 0;
}
bool bol = bol_;
boost::lexer::detail::internals const& internals_ =
state_machine_.data();
again:
std::size_t const* lookup_ = &internals_._lookup[dfa_state_]->
front ();
std::size_t dfa_alphabet_ = internals_._dfa_alphabet[dfa_state_];
std::size_t const* dfa_ = &internals_._dfa[dfa_state_]->front ();
std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
Iterator curr_ = start_token_;
bool end_state_ = *ptr_ != 0;
std::size_t id_ = *(ptr_ + boost::lexer::id_index);
std::size_t uid_ = *(ptr_ + boost::lexer::unique_id_index);
std::size_t end_start_state_ = dfa_state_;
bool end_bol_ = bol_;
Iterator end_token_ = start_token_;
while (curr_ != end_)
{
std::size_t const BOL_state_ = ptr_[boost::lexer::bol_index];
std::size_t const EOL_state_ = ptr_[boost::lexer::eol_index];
if (BOL_state_ && bol)
{
ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
}
else if (EOL_state_ && *curr_ == '\n')
{
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
}
else
{
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
value_type;
typedef typename
boost::lexer::char_traits<value_type>::index_type
index_type;
index_type index =
boost::lexer::char_traits<value_type>::call(*curr_++);
bol = (index == '\n') ? true : false;
std::size_t const state_ = ptr_[
lookup_[static_cast<std::size_t>(index)]];
if (state_ == 0)
{
break;
}
ptr_ = &dfa_[state_ * dfa_alphabet_];
}
if (*ptr_)
{
end_state_ = true;
id_ = *(ptr_ + boost::lexer::id_index);
uid_ = *(ptr_ + boost::lexer::unique_id_index);
end_start_state_ = *(ptr_ + boost::lexer::state_index);
end_bol_ = bol;
end_token_ = curr_;
}
}
std::size_t const EOL_state_ = ptr_[boost::lexer::eol_index];
if (EOL_state_ && curr_ == end_)
{
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
if (*ptr_)
{
end_state_ = true;
id_ = *(ptr_ + boost::lexer::id_index);
uid_ = *(ptr_ + boost::lexer::unique_id_index);
end_start_state_ = *(ptr_ + boost::lexer::state_index);
end_bol_ = bol;
end_token_ = curr_;
}
}
if (end_state_) {
// return longest match
dfa_state_ = end_start_state_;
start_token_ = end_token_;
if (id_ == 0)
{
bol = end_bol_;
goto again;
}
else
{
bol_ = end_bol_;
}
}
else {
bol_ = (*start_token_ == '\n') ? true : false;
id_ = boost::lexer::npos;
uid_ = boost::lexer::npos;
}
unique_id_ = uid_;
return id_;
}
///////////////////////////////////////////////////////////////////////
static std::size_t next (
boost::lexer::basic_state_machine<char_type> const& state_machine_
, bool& bol_, Iterator &start_token_, Iterator const& end_
, std::size_t& unique_id_)
{
if (start_token_ == end_)
{
unique_id_ = boost::lexer::npos;
return 0;
}
bool bol = bol_;
std::size_t const* lookup_ = &state_machine_.data()._lookup[0]->front();
std::size_t dfa_alphabet_ = state_machine_.data()._dfa_alphabet[0];
std::size_t const* dfa_ = &state_machine_.data()._dfa[0]->front ();
std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
Iterator curr_ = start_token_;
bool end_state_ = *ptr_ != 0;
std::size_t id_ = *(ptr_ + boost::lexer::id_index);
std::size_t uid_ = *(ptr_ + boost::lexer::unique_id_index);
bool end_bol_ = bol_;
Iterator end_token_ = start_token_;
while (curr_ != end_)
{
std::size_t const BOL_state_ = ptr_[boost::lexer::bol_index];
std::size_t const EOL_state_ = ptr_[boost::lexer::eol_index];
if (BOL_state_ && bol)
{
ptr_ = &dfa_[BOL_state_ * dfa_alphabet_];
}
else if (EOL_state_ && *curr_ == '\n')
{
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
}
else
{
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
value_type;
typedef typename
boost::lexer::char_traits<value_type>::index_type
index_type;
index_type index =
boost::lexer::char_traits<value_type>::call(*curr_++);
bol = (index == '\n') ? true : false;
std::size_t const state_ = ptr_[
lookup_[static_cast<std::size_t>(index)]];
if (state_ == 0)
{
break;
}
ptr_ = &dfa_[state_ * dfa_alphabet_];
}
if (*ptr_)
{
end_state_ = true;
id_ = *(ptr_ + boost::lexer::id_index);
uid_ = *(ptr_ + boost::lexer::unique_id_index);
end_bol_ = bol;
end_token_ = curr_;
}
}
std::size_t const EOL_state_ = ptr_[boost::lexer::eol_index];
if (EOL_state_ && curr_ == end_)
{
ptr_ = &dfa_[EOL_state_ * dfa_alphabet_];
if (*ptr_)
{
end_state_ = true;
id_ = *(ptr_ + boost::lexer::id_index);
uid_ = *(ptr_ + boost::lexer::unique_id_index);
end_bol_ = bol;
end_token_ = curr_;
}
}
if (end_state_) {
// return longest match
bol_ = end_bol_;
start_token_ = end_token_;
}
else {
bol_ = *start_token_ == '\n';
id_ = boost::lexer::npos;
uid_ = boost::lexer::npos;
}
unique_id_ = uid_;
return id_;
}
};
}}}}
#endif
@@ -0,0 +1,399 @@
// 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_17_2007_0139PM)
#define BOOST_SPIRIT_LEX_LEXER_MAR_17_2007_0139PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <iosfwd>
#include <boost/spirit/home/support/detail/lexer/generator.hpp>
#include <boost/spirit/home/support/detail/lexer/rules.hpp>
#include <boost/spirit/home/support/detail/lexer/consts.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/token.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/functor.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/functor_data.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/iterator.hpp>
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
#include <boost/spirit/home/support/detail/lexer/debug.hpp>
#endif
#include <boost/foreach.hpp>
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
///////////////////////////////////////////////////////////////////////////
namespace detail
{
///////////////////////////////////////////////////////////////////////
// The must_escape function checks if the given character value needs
// to be preceded by a backslash character to disable its special
// meaning in the context of a regular expression
///////////////////////////////////////////////////////////////////////
template <typename Char>
inline bool must_escape(Char c)
{
// FIXME: more needed?
switch (c) {
case '+': case '/': case '*': case '?':
case '|':
case '(': case ')':
case '[': case ']':
case '{': case '}':
case '.':
case '^': case '$':
case '\\':
case '"':
return true;
default:
break;
}
return false;
}
///////////////////////////////////////////////////////////////////////
// The escape function returns the string representation of the given
// character value, possibly escaped with a backslash character, to
// allow it being safely used in a regular expression definition.
///////////////////////////////////////////////////////////////////////
template <typename Char>
inline std::basic_string<Char> escape(Char ch)
{
std::basic_string<Char> result(1, ch);
if (detail::must_escape(ch))
{
typedef typename std::basic_string<Char>::size_type size_type;
result.insert((size_type)0, 1, '\\');
}
return result;
}
///////////////////////////////////////////////////////////////////////
//
///////////////////////////////////////////////////////////////////////
inline boost::lexer::regex_flags map_flags(unsigned int flags)
{
unsigned int retval = boost::lexer::none;
if (flags & match_flags::match_not_dot_newline)
retval |= boost::lexer::dot_not_newline;
if (flags & match_flags::match_icase)
retval |= boost::lexer::icase;
return boost::lexer::regex_flags(retval);
}
}
///////////////////////////////////////////////////////////////////////////
template <typename Lexer, typename F>
bool generate_static(Lexer const&
, std::basic_ostream<typename Lexer::char_type>&
, typename Lexer::char_type const*, F);
///////////////////////////////////////////////////////////////////////////
//
// Every lexer type to be used as a lexer for Spirit has to conform to
// the following public interface:
//
// typedefs:
// iterator_type The type of the iterator exposed by this lexer.
// token_type The type of the tokens returned from the exposed
// iterators.
//
// functions:
// default constructor
// Since lexers are instantiated as base classes
// only it might be a good idea to make this
// constructor protected.
// begin, end Return a pair of iterators, when dereferenced
// returning the sequence of tokens recognized in
// the input stream given as the parameters to the
// begin() function.
// add_token Should add the definition of a token to be
// recognized by this lexer.
// clear Should delete all current token definitions
// associated with the given state of this lexer
// object.
//
// template parameters:
// Iterator The type of the iterator used to access the
// underlying character stream.
// Token The type of the tokens to be returned from the
// exposed token iterator.
// Functor The type of the InputPolicy to use to instantiate
// the multi_pass iterator type to be used as the
// token iterator (returned from begin()/end()).
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// The lexer class is a implementation of a Spirit.Lex lexer on
// top of Ben Hanson's lexertl library as outlined above (For more
// information about lexertl go here: http://www.benhanson.net/lexertl.html).
//
// This class is supposed to be used as the first and only template
// parameter while instantiating instances of a lex::lexer class.
//
///////////////////////////////////////////////////////////////////////////
template <typename Token = token<>
, typename Iterator = typename Token::iterator_type
, typename Functor = functor<Token, lexertl::detail::data, Iterator> >
class lexer
{
private:
struct dummy { void true_() {} };
typedef void (dummy::*safe_bool)();
static std::size_t const all_states_id = static_cast<std::size_t>(-2);
public:
operator safe_bool() const
{ return initialized_dfa_ ? &dummy::true_ : 0; }
typedef typename boost::detail::iterator_traits<Iterator>::value_type
char_type;
typedef std::basic_string<char_type> string_type;
typedef boost::lexer::basic_rules<char_type> basic_rules_type;
// Every lexer type to be used as a lexer for Spirit has to conform to
// a public interface .
typedef Token token_type;
typedef typename Token::id_type id_type;
typedef iterator<Functor> iterator_type;
private:
// this type is purely used for the iterator_type construction below
struct iterator_data_type
{
typedef typename Functor::semantic_actions_type semantic_actions_type;
iterator_data_type(
boost::lexer::basic_state_machine<char_type> const& sm
, boost::lexer::basic_rules<char_type> const& rules
, semantic_actions_type const& actions)
: state_machine_(sm), rules_(rules), actions_(actions)
{}
boost::lexer::basic_state_machine<char_type> const& state_machine_;
boost::lexer::basic_rules<char_type> const& rules_;
semantic_actions_type const& actions_;
private:
// silence MSVC warning C4512: assignment operator could not be generated
iterator_data_type& operator= (iterator_data_type const&);
};
public:
// Return the start iterator usable for iterating over the generated
// tokens.
iterator_type begin(Iterator& first, Iterator const& last
, char_type const* initial_state = 0) const
{
if (!init_dfa()) // never minimize DFA for dynamic lexers
return iterator_type();
iterator_data_type iterator_data(state_machine_, rules_, actions_);
return iterator_type(iterator_data, first, last, initial_state);
}
// Return the end iterator usable to stop iterating over the generated
// tokens.
iterator_type end() const
{
return iterator_type();
}
protected:
// Lexer instances can be created by means of a derived class only.
lexer(unsigned int flags)
: flags_(detail::map_flags(flags))
, rules_(flags_)
, initialized_dfa_(false)
{}
public:
// interface for token definition management
std::size_t add_token(char_type const* state, char_type tokendef,
std::size_t token_id, char_type const* targetstate)
{
add_state(state);
initialized_dfa_ = false;
if (state == all_states())
return rules_.add(state, detail::escape(tokendef), token_id, rules_.dot());
if (0 == targetstate)
targetstate = state;
else
add_state(targetstate);
return rules_.add(state, detail::escape(tokendef), token_id, targetstate);
}
std::size_t add_token(char_type const* state, string_type const& tokendef,
std::size_t token_id, char_type const* targetstate)
{
add_state(state);
initialized_dfa_ = false;
if (state == all_states())
return rules_.add(state, tokendef, token_id, rules_.dot());
if (0 == targetstate)
targetstate = state;
else
add_state(targetstate);
return rules_.add(state, tokendef, token_id, targetstate);
}
// interface for pattern definition management
void add_pattern (char_type const* state, string_type const& name,
string_type const& patterndef)
{
add_state(state);
rules_.add_macro(name.c_str(), patterndef);
initialized_dfa_ = false;
}
boost::lexer::rules const& get_rules() const { return rules_; }
void clear(char_type const* state)
{
std::size_t s = rules_.state(state);
if (boost::lexer::npos != s)
rules_.clear(state);
initialized_dfa_ = false;
}
std::size_t add_state(char_type const* state)
{
if (state == all_states())
return all_states_id;
std::size_t stateid = rules_.state(state);
if (boost::lexer::npos == stateid) {
stateid = rules_.add_state(state);
initialized_dfa_ = false;
}
return stateid;
}
string_type initial_state() const
{
return string_type(rules_.initial());
}
string_type all_states() const
{
return string_type(rules_.all_states());
}
// Register a semantic action with the given id
template <typename F>
void add_action(std::size_t unique_id, std::size_t state, F act)
{
// If you see an error here stating add_action is not a member of
// fusion::unused_type then you are probably having semantic actions
// attached to at least one token in the lexer definition without
// using the lex::lexertl::actor_lexer<> as its base class.
typedef typename Functor::wrap_action_type wrapper_type;
if (state == all_states_id) {
// add the action to all known states
typedef typename
basic_rules_type::string_size_t_map::value_type
state_type;
std::size_t states = rules_.statemap().size();
BOOST_FOREACH(state_type const& s, rules_.statemap()) {
for (std::size_t j = 0; j < states; ++j)
actions_.add_action(unique_id + j, s.second, wrapper_type::call(act));
}
}
else {
actions_.add_action(unique_id, state, wrapper_type::call(act));
}
}
// template <typename F>
// void add_action(std::size_t unique_id, char_type const* state, F act)
// {
// typedef typename Functor::wrap_action_type wrapper_type;
// actions_.add_action(unique_id, add_state(state), wrapper_type::call(act));
// }
// We do not minimize the state machine by default anymore because
// Ben said: "If you can afford to generate a lexer at runtime, there
// is little point in calling minimise."
// Go figure.
bool init_dfa(bool minimize = false) const
{
if (!initialized_dfa_) {
state_machine_.clear();
typedef boost::lexer::basic_generator<char_type> generator;
generator::build (rules_, state_machine_);
if (minimize)
generator::minimise (state_machine_);
#if defined(BOOST_SPIRIT_LEXERTL_DEBUG)
boost::lexer::debug::dump(state_machine_, std::cerr);
#endif
initialized_dfa_ = true;
// // release memory held by rules description
// basic_rules_type rules;
// rules.init_state_info(rules_); // preserve states
// std::swap(rules, rules_);
}
return true;
}
private:
// lexertl specific data
mutable boost::lexer::basic_state_machine<char_type> state_machine_;
boost::lexer::regex_flags flags_;
/*mutable*/ basic_rules_type rules_;
typename Functor::semantic_actions_type actions_;
mutable bool initialized_dfa_;
// generator functions must be able to access members directly
template <typename Lexer, typename F>
friend bool generate_static(Lexer const&
, std::basic_ostream<typename Lexer::char_type>&
, typename Lexer::char_type const*, F);
};
///////////////////////////////////////////////////////////////////////////
//
// The actor_lexer class is another implementation of a Spirit.Lex
// lexer on top of Ben Hanson's lexertl library as outlined above (For
// more information about lexertl go here:
// http://www.benhanson.net/lexertl.html).
//
// The only difference to the lexer class above is that token_def
// definitions may have semantic (lexer) actions attached while being
// defined:
//
// int w;
// token_def word = "[^ \t\n]+";
// self = word[++ref(w)]; // see example: word_count_lexer
//
// This class is supposed to be used as the first and only template
// parameter while instantiating instances of a lex::lexer class.
//
///////////////////////////////////////////////////////////////////////////
template <typename Token = token<>
, typename Iterator = typename Token::iterator_type
, typename Functor = functor<Token, lexertl::detail::data, Iterator, mpl::true_> >
class actor_lexer : public lexer<Token, Iterator, Functor>
{
protected:
// Lexer instances can be created by means of a derived class only.
actor_lexer(unsigned int flags)
: lexer<Token, Iterator, Functor>(flags) {}
};
}}}}
#endif
@@ -0,0 +1,930 @@
// 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_POSITION_TOKEN_MAY_13_2011_0846PM)
#define BOOST_SPIRIT_LEX_POSITION_TOKEN_MAY_13_2011_0846PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/spirit/home/qi/detail/assign_to.hpp>
#include <boost/spirit/home/support/attributes.hpp>
#include <boost/spirit/home/support/argument.hpp>
#include <boost/spirit/home/support/detail/lexer/generator.hpp>
#include <boost/spirit/home/support/detail/lexer/rules.hpp>
#include <boost/spirit/home/support/detail/lexer/consts.hpp>
#include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
#include <boost/spirit/home/lex/lexer/terminals.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/static_assert.hpp>
#if defined(BOOST_SPIRIT_DEBUG)
#include <iosfwd>
#endif
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
///////////////////////////////////////////////////////////////////////////
//
// The position_token is the type of the objects returned by the
// iterator if it has been specified while instantiating the lexer object.
//
// template parameters:
// Iterator The type of the iterator used to access the
// underlying character stream.
// AttributeTypes A mpl sequence containing the types of all
// required different token values to be supported
// by this token type.
// HasState A mpl::bool_ indicating, whether this token type
// should support lexer states.
// Idtype The type to use for the token id (defaults to
// std::size_t).
//
// It is possible to use other token types with the spirit::lex
// framework as well. If you plan to use a different type as your token
// type, you'll need to expose the following things from your token type
// to make it compatible with spirit::lex:
//
// typedefs
// iterator_type The type of the iterator used to access the
// underlying character stream.
//
// id_type The type of the token id used.
//
// methods
// default constructor
// This should initialize the token as an end of
// input token.
// constructors The prototype of the other required
// constructors should be:
//
// token(int)
// This constructor should initialize the token as
// an invalid token (not carrying any specific
// values)
//
// where: the int is used as a tag only and its value is
// ignored
//
// and:
//
// token(Idtype id, std::size_t state,
// iterator_type first, iterator_type last);
//
// where: id: token id
// state: lexer state this token was matched in
// first, last: pair of iterators marking the matched
// range in the underlying input stream
//
// accessors
// id() return the token id of the matched input sequence
// id(newid) set the token id of the token instance
//
// state() return the lexer state this token was matched in
//
// value() return the token value
//
// Additionally, you will have to implement a couple of helper functions
// in the same namespace as the token type: a comparison operator==() to
// compare your token instances, a token_is_valid() function and different
// specializations of the Spirit customization point
// assign_to_attribute_from_value as shown below.
//
///////////////////////////////////////////////////////////////////////////
template <typename Iterator = char const*
, typename AttributeTypes = mpl::vector0<>
, typename HasState = mpl::true_
, typename Idtype = std::size_t>
struct position_token;
///////////////////////////////////////////////////////////////////////////
// This specialization of the token type doesn't contain any item data and
// doesn't support working with lexer states. Although, like all other
// variants of position_token, it carries a pair of iterators marking the
// begin and the end of the matched character sequence.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Idtype>
struct position_token<Iterator, lex::omit, mpl::false_, Idtype>
{
typedef Iterator iterator_type;
typedef iterator_range<iterator_type> iterpair_type;
typedef mpl::false_ has_state;
typedef Idtype id_type;
typedef unused_type token_value_type;
// default constructed tokens correspond to EOI tokens
position_token()
: id_(id_type(boost::lexer::npos)) {}
// construct an invalid token
explicit position_token(int)
: id_(id_type(0)) {}
position_token(id_type id, std::size_t)
: id_(id) {}
position_token(id_type id, std::size_t, token_value_type)
: id_(id) {}
position_token(id_type id, std::size_t, Iterator const& first
, Iterator const& last)
: id_(id), matched_(first, last) {}
// this default conversion operator is needed to allow the direct
// usage of tokens in conjunction with the primitive parsers defined
// in Qi
operator id_type() const { return id_; }
// Retrieve or set the token id of this token instance.
id_type id() const { return id_; }
void id(id_type newid) { id_ = newid; }
std::size_t state() const { return 0; } // always '0' (INITIAL state)
bool is_valid() const
{
return 0 != id_ && id_type(boost::lexer::npos) != id_;
}
// access the stored iterator range of the matched input sequence
iterator_type begin() const { return matched_.begin(); }
iterator_type end() const { return matched_.end(); }
iterpair_type& matched() { return matched_; }
iterpair_type const& matched() const { return matched_; }
token_value_type& value() { static token_value_type u; return u; }
token_value_type const& value() const { return unused; }
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
// workaround for MSVC10 which has problems copying a default
// constructed iterator_range
position_token& operator= (position_token const& rhs)
{
if (this != &rhs)
{
id_ = rhs.id_;
if (is_valid())
matched_ = rhs.matched_;
}
return *this;
}
#endif
protected:
id_type id_; // token id, 0 if nothing has been matched
iterpair_type matched_; // matched input sequence
};
#if defined(BOOST_SPIRIT_DEBUG)
template <typename Char, typename Traits, typename Iterator
, typename AttributeTypes, typename HasState, typename Idtype>
inline std::basic_ostream<Char, Traits>&
operator<< (std::basic_ostream<Char, Traits>& os
, position_token<Iterator, AttributeTypes, HasState, Idtype> const& t)
{
if (t.is_valid()) {
Iterator end = t.end();
for (Iterator it = t.begin(); it != end; ++it)
os << *it;
}
else {
os << "<invalid token>";
}
return os;
}
#endif
///////////////////////////////////////////////////////////////////////////
// This specialization of the token type doesn't contain any item data but
// supports working with lexer states.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Idtype>
struct position_token<Iterator, lex::omit, mpl::true_, Idtype>
: position_token<Iterator, lex::omit, mpl::false_, Idtype>
{
private:
typedef position_token<Iterator, lex::omit, mpl::false_, Idtype>
base_type;
public:
typedef typename base_type::id_type id_type;
typedef Iterator iterator_type;
typedef mpl::true_ has_state;
typedef unused_type token_value_type;
// default constructed tokens correspond to EOI tokens
position_token() : state_(boost::lexer::npos) {}
// construct an invalid token
explicit position_token(int)
: base_type(0), state_(boost::lexer::npos) {}
position_token(id_type id, std::size_t state)
: base_type(id, boost::lexer::npos), state_(state) {}
position_token(id_type id, std::size_t state, token_value_type)
: base_type(id, boost::lexer::npos, unused)
, state_(state) {}
position_token(id_type id, std::size_t state
, Iterator const& first, Iterator const& last)
: base_type(id, boost::lexer::npos, first, last)
, state_(state) {}
std::size_t state() const { return state_; }
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
// workaround for MSVC10 which has problems copying a default
// constructed iterator_range
position_token& operator= (position_token const& rhs)
{
if (this != &rhs)
{
this->base_type::operator=(static_cast<base_type const&>(rhs));
state_ = rhs.state_;
}
return *this;
}
#endif
protected:
std::size_t state_; // lexer state this token was matched in
};
///////////////////////////////////////////////////////////////////////////
// These specializations for an empty attribute list cause all token
// instances to expose as it attribute the iterator_range pointing to the
// matched input sequence.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename HasState, typename Idtype>
struct position_token<Iterator, mpl::vector<>, HasState, Idtype>
: position_token<Iterator, lex::omit, HasState, Idtype>
{
private:
typedef position_token<Iterator, lex::omit, HasState, Idtype> base_type;
public:
typedef typename base_type::id_type id_type;
typedef typename base_type::iterator_type iterator_type;
typedef typename base_type::iterpair_type iterpair_type;
typedef HasState has_state;
typedef iterpair_type token_value_type;
// default constructed tokens correspond to EOI tokens
position_token() {}
// construct an invalid token
explicit position_token(int)
: base_type(0) {}
position_token(id_type id, std::size_t state)
: base_type(id, state) {}
position_token(id_type id, std::size_t state, token_value_type)
: base_type(id, state, unused) {}
position_token(id_type id, std::size_t state
, Iterator const& first, Iterator const& last)
: base_type(id, state, first, last) {}
token_value_type& value() { return this->base_type::matched(); }
token_value_type const& value() const { return this->base_type::matched(); }
};
template <typename Iterator, typename HasState, typename Idtype>
struct position_token<Iterator, mpl::vector0<>, HasState, Idtype>
: position_token<Iterator, lex::omit, HasState, Idtype>
{
private:
typedef position_token<Iterator, lex::omit, HasState, Idtype> base_type;
public:
typedef typename base_type::id_type id_type;
typedef typename base_type::iterator_type iterator_type;
typedef typename base_type::iterpair_type iterpair_type;
typedef HasState has_state;
typedef iterpair_type token_value_type;
// default constructed tokens correspond to EOI tokens
position_token() {}
// construct an invalid token
explicit position_token(int)
: base_type(0) {}
position_token(id_type id, std::size_t state)
: base_type(id, state) {}
position_token(id_type id, std::size_t state, token_value_type)
: base_type(id, state, unused) {}
position_token(id_type id, std::size_t state
, Iterator const& first, Iterator const& last)
: base_type(id, state, first, last) {}
token_value_type& value() { return this->base_type::matched(); }
token_value_type const& value() const { return this->base_type::matched(); }
};
///////////////////////////////////////////////////////////////////////////
// These specializations for an attribute list of length one cause all token
// instances to expose the specified type as its attribute.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Attribute, typename HasState
, typename Idtype>
struct position_token<Iterator, mpl::vector<Attribute>, HasState, Idtype>
: position_token<Iterator, lex::omit, HasState, Idtype>
{
private:
typedef position_token<Iterator, lex::omit, HasState, Idtype> base_type;
public:
typedef typename base_type::id_type id_type;
typedef typename base_type::iterator_type iterator_type;
typedef typename base_type::iterpair_type iterpair_type;
typedef HasState has_state;
typedef boost::optional<Attribute> token_value_type;
// default constructed tokens correspond to EOI tokens
position_token() {}
// construct an invalid token
explicit position_token(int)
: base_type(0) {}
position_token(id_type id, std::size_t state)
: base_type(id, state) {}
position_token(id_type id, std::size_t state, token_value_type const& v)
: base_type(id, state, unused), value_(v) {}
position_token(id_type id, std::size_t state
, Iterator const& first, Iterator const& last)
: base_type(id, state, first, last) {}
token_value_type& value() { return value_; }
token_value_type const& value() const { return value_; }
bool has_value() const { return !!value_; }
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
// workaround for MSVC10 which has problems copying a default
// constructed iterator_range
position_token& operator= (position_token const& rhs)
{
if (this != &rhs)
{
this->base_type::operator=(static_cast<base_type const&>(rhs));
if (this->is_valid())
value_ = rhs.value_;
}
return *this;
}
#endif
protected:
token_value_type value_; // token value
};
template <typename Iterator, typename Attribute, typename HasState
, typename Idtype>
struct position_token<Iterator, mpl::vector1<Attribute>, HasState, Idtype>
: position_token<Iterator, lex::omit, HasState, Idtype>
{
private:
typedef position_token<Iterator, lex::omit, HasState, Idtype> base_type;
public:
typedef typename base_type::id_type id_type;
typedef typename base_type::iterator_type iterator_type;
typedef typename base_type::iterpair_type iterpair_type;
typedef HasState has_state;
typedef boost::optional<Attribute> token_value_type;
// default constructed tokens correspond to EOI tokens
position_token() {}
// construct an invalid token
explicit position_token(int)
: base_type(0) {}
position_token(id_type id, std::size_t state)
: base_type(id, state) {}
position_token(id_type id, std::size_t state, token_value_type const& v)
: base_type(id, state, unused), value_(v) {}
position_token(id_type id, std::size_t state
, Iterator const& first, Iterator const& last)
: base_type(id, state, first, last) {}
token_value_type& value() { return value_; }
token_value_type const& value() const { return value_; }
bool has_value() const { return value_; }
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
// workaround for MSVC10 which has problems copying a default
// constructed iterator_range
position_token& operator= (position_token const& rhs)
{
if (this != &rhs)
{
this->base_type::operator=(static_cast<base_type const&>(rhs));
if (this->is_valid())
value_ = rhs.value_;
}
return *this;
}
#endif
protected:
token_value_type value_; // token value
};
///////////////////////////////////////////////////////////////////////////
// The generic version of the position_token type derives from the
// specialization above and adds a single data member holding the item
// data carried by the token instance.
///////////////////////////////////////////////////////////////////////////
namespace detail
{
///////////////////////////////////////////////////////////////////////
// Meta-function to calculate the type of the variant data item to be
// stored with each token instance.
//
// Note: The iterator pair needs to be the first type in the list of
// types supported by the generated variant type (this is being
// used to identify whether the stored data item in a particular
// token instance needs to be converted from the pair of
// iterators (see the first of the assign_to_attribute_from_value
// specializations below).
///////////////////////////////////////////////////////////////////////
template <typename IteratorPair, typename AttributeTypes>
struct position_token_value_typesequence
{
typedef typename mpl::insert<
AttributeTypes
, typename mpl::begin<AttributeTypes>::type
, IteratorPair
>::type sequence_type;
typedef typename make_variant_over<sequence_type>::type type;
};
///////////////////////////////////////////////////////////////////////
// The type of the data item stored with a token instance is defined
// by the template parameter 'AttributeTypes' and may be:
//
// lex::omit: no data item is stored with the token
// instance (this is handled by the
// specializations of the token class
// below)
// mpl::vector0<>: each token instance stores a pair of
// iterators pointing to the matched input
// sequence
// mpl::vector<...>: each token instance stores a variant being
// able to store the pair of iterators pointing
// to the matched input sequence, or any of the
// types a specified in the mpl::vector<>
//
// All this is done to ensure the token type is as small (in terms
// of its byte-size) as possible.
///////////////////////////////////////////////////////////////////////
template <typename IteratorPair, typename AttributeTypes>
struct position_token_value
: mpl::eval_if<
mpl::or_<
is_same<AttributeTypes, mpl::vector0<> >
, is_same<AttributeTypes, mpl::vector<> > >
, mpl::identity<IteratorPair>
, position_token_value_typesequence<IteratorPair, AttributeTypes> >
{};
}
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype>
struct position_token
: position_token<Iterator, lex::omit, HasState, Idtype>
{
private: // precondition assertions
BOOST_STATIC_ASSERT((mpl::is_sequence<AttributeTypes>::value ||
is_same<AttributeTypes, lex::omit>::value));
typedef position_token<Iterator, lex::omit, HasState, Idtype>
base_type;
protected:
// If no additional token value types are given, the token will
// hold no token value at all as the base class already has the
// iterator pair of the matched range in the underlying input sequence.
// Otherwise the token value is stored as a variant and will
// initially hold an unused_type but is able to hold any of
// the given data types as well. The conversion from the iterator pair
// to the required data type is done when it is accessed for the first
// time.
typedef iterator_range<Iterator> iterpair_type;
public:
typedef typename base_type::id_type id_type;
typedef typename detail::position_token_value<
iterpair_type, AttributeTypes>::type token_value_type;
typedef Iterator iterator_type;
// default constructed tokens correspond to EOI tokens
position_token() {}
// construct an invalid token
explicit position_token(int)
: base_type(0) {}
position_token(id_type id, std::size_t state, token_value_type const& value)
: base_type(id, state, value), value_(value) {}
position_token(id_type id, std::size_t state, Iterator const& first
, Iterator const& last)
: base_type(id, state, first, last)
, value_(iterpair_type(first, last))
{}
token_value_type& value() { return value_; }
token_value_type const& value() const { return value_; }
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
// workaround for MSVC10 which has problems copying a default
// constructed iterator_range
position_token& operator= (position_token const& rhs)
{
if (this != &rhs)
{
this->base_type::operator=(static_cast<base_type const&>(rhs));
if (this->is_valid())
value_ = rhs.value_;
}
return *this;
}
#endif
protected:
token_value_type value_; // token value, by default a pair of iterators
};
///////////////////////////////////////////////////////////////////////////
// tokens are considered equal, if their id's match (these are unique)
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype>
inline bool
operator== (position_token<Iterator, AttributeTypes, HasState, Idtype> const& lhs,
position_token<Iterator, AttributeTypes, HasState, Idtype> const& rhs)
{
return lhs.id() == rhs.id();
}
///////////////////////////////////////////////////////////////////////////
// This overload is needed by the multi_pass/functor_input_policy to
// validate a token instance. It has to be defined in the same namespace
// as the token class itself to allow ADL to find it.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype>
inline bool
token_is_valid(position_token<Iterator, AttributeTypes, HasState, Idtype> const& t)
{
return t.is_valid();
}
}}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// We have to provide specializations for the customization point
// assign_to_attribute_from_value allowing to extract the needed value
// from the token.
///////////////////////////////////////////////////////////////////////////
// This is called from the parse function of token_def if the token_def
// has been defined to carry a special attribute type
template <typename Attribute, typename Iterator, typename AttributeTypes
, typename HasState, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::position_token<Iterator, AttributeTypes, HasState, Idtype> >
{
static void
call(lex::lexertl::position_token<
Iterator, AttributeTypes, HasState, Idtype> const& t
, Attribute& attr)
{
// The goal of this function is to avoid the conversion of the pair of
// iterators (to the matched character sequence) into the token value
// of the required type being done more than once. For this purpose it
// checks whether the stored value type is still the default one (pair
// of iterators) and if yes, replaces the pair of iterators with the
// converted value to be returned from subsequent calls.
if (0 == t.value().which()) {
// first access to the token value
typedef iterator_range<Iterator> iterpair_type;
iterpair_type const& ip = t.matched();
// Interestingly enough we use the assign_to() framework defined in
// Spirit.Qi allowing to convert the pair of iterators to almost any
// required type (assign_to(), if available, uses the standard Spirit
// parsers to do the conversion).
spirit::traits::assign_to(ip.begin(), ip.end(), attr);
// If you get an error during the compilation of the following
// assignment expression, you probably forgot to list one or more
// types used as token value types (in your token_def<...>
// definitions) in your definition of the token class. I.e. any token
// value type used for a token_def<...> definition has to be listed
// during the declaration of the token type to use. For instance let's
// assume we have two token_def's:
//
// token_def<int> number; number = "...";
// token_def<std::string> identifier; identifier = "...";
//
// Then you'll have to use the following token type definition
// (assuming you are using the token class):
//
// typedef mpl::vector<int, std::string> token_values;
// typedef token<base_iter_type, token_values> token_type;
//
// where: base_iter_type is the iterator type used to expose the
// underlying input stream.
//
// This token_type has to be used as the second template parameter
// to the lexer class:
//
// typedef lexer<base_iter_type, token_type> lexer_type;
//
// again, assuming you're using the lexer<> template for your
// tokenization.
typedef lex::lexertl::position_token<
Iterator, AttributeTypes, HasState, Idtype> token_type;
spirit::traits::assign_to(
attr, const_cast<token_type&>(t).value()); // re-assign value
}
else {
// reuse the already assigned value
spirit::traits::assign_to(get<Attribute>(t.value()), attr);
}
}
};
template <typename Attribute, typename Iterator, typename AttributeTypes
, typename HasState, typename Idtype>
struct assign_to_container_from_value<Attribute
, lex::lexertl::position_token<Iterator, AttributeTypes, HasState, Idtype> >
: assign_to_attribute_from_value<Attribute
, lex::lexertl::position_token<Iterator, AttributeTypes, HasState, Idtype> >
{};
///////////////////////////////////////////////////////////////////////////
// These are called from the parse function of token_def if the token type
// has no special attribute type assigned
template <typename Attribute, typename Iterator, typename HasState
, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::position_token<Iterator, mpl::vector0<>, HasState, Idtype> >
{
static void
call(lex::lexertl::position_token<
Iterator, mpl::vector0<>, HasState, Idtype> const& t
, Attribute& attr)
{
// The default type returned by the token_def parser component (if
// it has no token value type assigned) is the pair of iterators
// to the matched character sequence.
spirit::traits::assign_to(t.begin(), t.end(), attr);
}
};
// template <typename Attribute, typename Iterator, typename HasState
// , typename Idtype>
// struct assign_to_container_from_value<Attribute
// , lex::lexertl::position_token<Iterator, mpl::vector0<>, HasState, Idtype> >
// : assign_to_attribute_from_value<Attribute
// , lex::lexertl::position_token<Iterator, mpl::vector0<>, HasState, Idtype> >
// {};
// same as above but using mpl::vector<> instead of mpl::vector0<>
template <typename Attribute, typename Iterator, typename HasState
, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::position_token<Iterator, mpl::vector<>, HasState, Idtype> >
{
static void
call(lex::lexertl::position_token<
Iterator, mpl::vector<>, HasState, Idtype> const& t
, Attribute& attr)
{
// The default type returned by the token_def parser component (if
// it has no token value type assigned) is the pair of iterators
// to the matched character sequence.
spirit::traits::assign_to(t.begin(), t.end(), attr);
}
};
// template <typename Attribute, typename Iterator, typename HasState
// , typename Idtype>
// struct assign_to_container_from_value<Attribute
// , lex::lexertl::position_token<Iterator, mpl::vector<>, HasState, Idtype> >
// : assign_to_attribute_from_value<Attribute
// , lex::lexertl::position_token<Iterator, mpl::vector<>, HasState, Idtype> >
// {};
///////////////////////////////////////////////////////////////////////////
// These are called from the parse function of token_def if the token type
// has no special attribute type assigned
template <typename Attribute, typename Iterator, typename Attr
, typename HasState, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::position_token<Iterator, mpl::vector1<Attr>, HasState, Idtype> >
{
static void
call(lex::lexertl::position_token<
Iterator, mpl::vector1<Attr>, HasState, Idtype> const& t
, Attribute& attr)
{
// The goal of this function is to avoid the conversion of the pair of
// iterators (to the matched character sequence) into the token value
// of the required type being done more than once.
if (!t.has_value()) {
// first access to the token value
typedef iterator_range<Iterator> iterpair_type;
iterpair_type const& ip = t.matched();
// Interestingly enough we use the assign_to() framework defined in
// Spirit.Qi allowing to convert the pair of iterators to almost any
// required type (assign_to(), if available, uses the standard Spirit
// parsers to do the conversion).
spirit::traits::assign_to(ip.begin(), ip.end(), attr);
// Re-assign the attribute to the stored value
typedef lex::lexertl::position_token<
Iterator, mpl::vector1<Attr>, HasState, Idtype> token_type;
spirit::traits::assign_to(
attr, const_cast<token_type&>(t).value());
}
else {
// reuse the already assigned value
spirit::traits::assign_to(t.value(), attr);
}
}
};
// template <typename Attribute, typename Iterator, typename Attr
// , typename HasState, typename Idtype>
// struct assign_to_container_from_value<Attribute
// , lex::lexertl::position_token<Iterator, mpl::vector1<Attr>, HasState, Idtype> >
// : assign_to_attribute_from_value<Attribute
// , lex::lexertl::position_token<Iterator, mpl::vector1<Attr>, HasState, Idtype> >
// {};
// same as above but using mpl::vector<Attr> instead of mpl::vector1<Attr>
template <typename Attribute, typename Iterator, typename Attr
, typename HasState, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::position_token<Iterator, mpl::vector<Attr>, HasState, Idtype> >
{
static void
call(lex::lexertl::position_token<
Iterator, mpl::vector<Attr>, HasState, Idtype> const& t
, Attribute& attr)
{
// The goal of this function is to avoid the conversion of the pair of
// iterators (to the matched character sequence) into the token value
// of the required type being done more than once.
if (!t.has_value()) {
// first access to the token value
typedef iterator_range<Iterator> iterpair_type;
iterpair_type const& ip = t.matched();
// Interestingly enough we use the assign_to() framework defined in
// Spirit.Qi allowing to convert the pair of iterators to almost any
// required type (assign_to(), if available, uses the standard Spirit
// parsers to do the conversion).
spirit::traits::assign_to(ip.begin(), ip.end(), attr);
// Re-assign the attribute to the stored value
typedef lex::lexertl::position_token<
Iterator, mpl::vector<Attr>, HasState, Idtype> token_type;
spirit::traits::assign_to(
attr, const_cast<token_type&>(t).value());
}
else {
// reuse the already assigned value
spirit::traits::assign_to(t.value(), attr);
}
}
};
// template <typename Attribute, typename Iterator, typename Attr
// , typename HasState, typename Idtype>
// struct assign_to_container_from_value<Attribute
// , lex::lexertl::position_token<Iterator, mpl::vector<Attr>, HasState, Idtype> >
// : assign_to_attribute_from_value<Attribute
// , lex::lexertl::position_token<Iterator, mpl::vector<Attr>, HasState, Idtype> >
// {};
// This is called from the parse function of token_def if the token type
// has been explicitly omitted (i.e. no attribute value is used), which
// essentially means that every attribute gets initialized using default
// constructed values.
template <typename Attribute, typename Iterator, typename HasState
, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::position_token<Iterator, lex::omit, HasState, Idtype> >
{
static void
call(lex::lexertl::position_token<Iterator, lex::omit, HasState, Idtype> const& t
, Attribute& attr)
{
// do nothing
}
};
template <typename Attribute, typename Iterator, typename HasState
, typename Idtype>
struct assign_to_container_from_value<Attribute
, lex::lexertl::position_token<Iterator, lex::omit, HasState, Idtype> >
: assign_to_attribute_from_value<Attribute
, lex::lexertl::position_token<Iterator, lex::omit, HasState, Idtype> >
{};
// This is called from the parse function of lexer_def_
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype_, typename Idtype>
struct assign_to_attribute_from_value<
fusion::vector2<Idtype_, iterator_range<Iterator> >
, lex::lexertl::position_token<Iterator, AttributeTypes, HasState, Idtype> >
{
static void
call(lex::lexertl::position_token<Iterator, AttributeTypes, HasState, Idtype> const& t
, fusion::vector2<Idtype_, iterator_range<Iterator> >& attr)
{
// The type returned by the lexer_def_ parser components is a
// fusion::vector containing the token id of the matched token
// and the pair of iterators to the matched character sequence.
typedef iterator_range<Iterator> iterpair_type;
typedef fusion::vector2<Idtype_, iterator_range<Iterator> >
attribute_type;
iterpair_type const& ip = t.matched();
attr = attribute_type(t.id(), ip);
}
};
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype_, typename Idtype>
struct assign_to_container_from_value<
fusion::vector2<Idtype_, iterator_range<Iterator> >
, lex::lexertl::position_token<Iterator, AttributeTypes, HasState, Idtype> >
: assign_to_attribute_from_value<
fusion::vector2<Idtype_, iterator_range<Iterator> >
, lex::lexertl::position_token<Iterator, AttributeTypes, HasState, Idtype> >
{};
///////////////////////////////////////////////////////////////////////////
// Overload debug output for a single token, this integrates lexer tokens
// with Qi's simple_trace debug facilities
template <typename Iterator, typename Attribute, typename HasState
, typename Idtype>
struct token_printer_debug<
lex::lexertl::position_token<Iterator, Attribute, HasState, Idtype> >
{
typedef lex::lexertl::position_token<Iterator, Attribute, HasState, Idtype> token_type;
template <typename Out>
static void print(Out& out, token_type const& val)
{
out << '[';
spirit::traits::print_token(out, val.value());
out << ']';
}
};
}}}
#endif
@@ -0,0 +1,121 @@
// 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_SEMANTIC_ACTION_DATA_JUN_10_2009_0417PM)
#define BOOST_SPIRIT_LEX_LEXER_SEMANTIC_ACTION_DATA_JUN_10_2009_0417PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/lexer/pass_flags.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/function.hpp>
#include <vector>
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
namespace detail
{
///////////////////////////////////////////////////////////////////////
template <typename Iterator, typename SupportsState, typename Data>
struct semantic_actions;
// This specialization of semantic_actions will be used if the token
// type (lexer definition) does not support states, which simplifies
// the data structures used to store the semantic action function
// objects.
template <typename Iterator, typename Data>
struct semantic_actions<Iterator, mpl::false_, Data>
{
typedef void functor_type(Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&, std::size_t&, Data&);
typedef boost::function<functor_type> functor_wrapper_type;
// add a semantic action function object
template <typename F>
void add_action(std::size_t unique_id, std::size_t, F act)
{
if (actions_.size() <= unique_id)
actions_.resize(unique_id + 1);
actions_[unique_id] = act;
}
// try to invoke a semantic action for the given token (unique_id)
BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t /*state*/
, std::size_t& id, std::size_t unique_id, Iterator& end
, Data& data) const
{
// if there is nothing to invoke, continue with 'match'
if (unique_id >= actions_.size() || !actions_[unique_id])
return pass_flags::pass_normal;
// Note: all arguments might be changed by the invoked semantic
// action
BOOST_SCOPED_ENUM(pass_flags) match = pass_flags::pass_normal;
actions_[unique_id](data.get_first(), end, match, id, data);
return match;
}
std::vector<functor_wrapper_type> actions_;
};
// This specialization of semantic_actions will be used if the token
// type (lexer definition) needs to support states, resulting in a more
// complex data structure needed for storing the semantic action
// function objects.
template <typename Iterator, typename Data>
struct semantic_actions<Iterator, mpl::true_, Data>
{
typedef void functor_type(Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&, std::size_t&, Data&);
typedef boost::function<functor_type> functor_wrapper_type;
// add a semantic action function object
template <typename F>
void add_action(std::size_t unique_id, std::size_t state, F act)
{
if (actions_.size() <= state)
actions_.resize(state + 1);
std::vector<functor_wrapper_type>& actions (actions_[state]);
if (actions.size() <= unique_id)
actions.resize(unique_id + 1);
actions[unique_id] = act;
}
// try to invoke a semantic action for the given token (unique_id)
BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t state
, std::size_t& id, std::size_t unique_id, Iterator& end
, Data& data) const
{
// if there is no action defined for this state, return match
if (state >= actions_.size())
return pass_flags::pass_normal;
// if there is nothing to invoke, continue with 'match'
std::vector<functor_wrapper_type> const& actions = actions_[state];
if (unique_id >= actions.size() || !actions[unique_id])
return pass_flags::pass_normal;
// set token value
data.set_end(end);
// Note: all arguments might be changed by the invoked semantic
// action
BOOST_SCOPED_ENUM(pass_flags) match = pass_flags::pass_normal;
actions[unique_id](data.get_first(), end, match, id, data);
return match;
}
std::vector<std::vector<functor_wrapper_type> > actions_;
};
}
}}}}
#endif
@@ -0,0 +1,572 @@
// 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_STATIC_FUNCTOR_DATA_FEB_10_2008_0755PM)
#define BOOST_SPIRIT_LEX_LEXER_STATIC_FUNCTOR_DATA_FEB_10_2008_0755PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/detail/lexer/generator.hpp>
#include <boost/spirit/home/support/detail/lexer/rules.hpp>
#include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/iterator_tokenizer.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/semantic_action_data.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/wrap_action.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/algorithm/string/predicate.hpp>
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
namespace detail
{
///////////////////////////////////////////////////////////////////////
template <typename Char, typename F>
inline std::size_t get_state_id(Char const* state, F f
, std::size_t numstates)
{
for (std::size_t i = 0; i < numstates; ++i)
{
if (boost::algorithm::equals(f(i), state))
return i;
}
return boost::lexer::npos;
}
///////////////////////////////////////////////////////////////////////
template <typename Iterator, typename HasActors, typename HasState
, typename TokenValue>
class static_data; // no default specialization
///////////////////////////////////////////////////////////////////////
// doesn't support no state and no actors
template <typename Iterator, typename TokenValue>
class static_data<Iterator, mpl::false_, mpl::false_, TokenValue>
{
protected:
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
char_type;
public:
typedef Iterator base_iterator_type;
typedef iterator_range<Iterator> token_value_type;
typedef token_value_type get_value_type;
typedef std::size_t state_type;
typedef char_type const* state_name_type;
typedef unused_type semantic_actions_type;
typedef detail::wrap_action<unused_type, Iterator, static_data
, std::size_t> wrap_action_type;
typedef std::size_t (*next_token_functor)(std::size_t&,
bool&, Iterator&, Iterator const&, std::size_t&);
typedef char_type const* (*get_state_name_type)(std::size_t);
// initialize the shared data
template <typename IterData>
static_data (IterData const& data, Iterator& first
, Iterator const& last)
: first_(first), last_(last)
, next_token_(data.next_)
, get_state_name_(data.get_state_name_)
, bol_(data.bol_) {}
// The following functions are used by the implementation of the
// placeholder '_state'.
template <typename Char>
void set_state_name (Char const*)
{
// some (random) versions of gcc instantiate this function even if it's not
// needed leading to false static asserts
#if !defined(__GNUC__)
// If you see a compile time assertion below you're probably
// using a token type not supporting lexer states (the 3rd
// template parameter of the token is mpl::false_), but your
// code uses state changes anyways.
BOOST_STATIC_ASSERT(false);
#endif
}
char_type const* get_state_name() const
{
return get_state_name_(0);
}
std::size_t get_state_id(char_type const*) const
{
return 0;
}
// The function get_eoi() is used by the implementation of the
// placeholder '_eoi'.
Iterator const& get_eoi() const { return last_; }
// The function less() is used by the implementation of the support
// function lex::less(). Its functionality is equivalent to flex'
// function yyless(): it returns an iterator positioned to the
// nth input character beyond the current start iterator (i.e. by
// assigning the return value to the placeholder '_end' it is
// possible to return all but the first n characters of the current
// token back to the input stream.
//
// This function does nothing as long as no semantic actions are
// used.
Iterator const& less(Iterator const& it, int)
{
// The following assertion fires most likely because you are
// using lexer semantic actions without using the actor_lexer
// as the base class for your token definition class.
BOOST_ASSERT(false &&
"Are you using lexer semantic actions without using the "
"actor_lexer base?");
return it;
}
// The function more() is used by the implementation of the support
// function lex::more(). Its functionality is equivalent to flex'
// function yymore(): it tells the lexer that the next time it
// matches a rule, the corresponding token should be appended onto
// the current token value rather than replacing it.
//
// These functions do nothing as long as no semantic actions are
// used.
void more()
{
// The following assertion fires most likely because you are
// using lexer semantic actions without using the actor_lexer
// as the base class for your token definition class.
BOOST_ASSERT(false &&
"Are you using lexer semantic actions without using the "
"actor_lexer base?");
}
bool adjust_start() { return false; }
void revert_adjust_start() {}
// The function lookahead() is used by the implementation of the
// support function lex::lookahead. It can be used to implement
// lookahead for lexer engines not supporting constructs like flex'
// a/b (match a, but only when followed by b):
//
// This function does nothing as long as no semantic actions are
// used.
bool lookahead(std::size_t, std::size_t /*state*/ = std::size_t(~0))
{
// The following assertion fires most likely because you are
// using lexer semantic actions without using the actor_lexer
// as the base class for your token definition class.
BOOST_ASSERT(false &&
"Are you using lexer semantic actions without using the "
"actor_lexer base?");
return false;
}
// the functions next, invoke_actions, and get_state are used by
// the functor implementation below
// The function next() tries to match the next token from the
// underlying input sequence.
std::size_t next(Iterator& end, std::size_t& unique_id, bool& prev_bol)
{
prev_bol = bol_;
std::size_t state = 0;
return next_token_(state, bol_, end, last_, unique_id);
}
// nothing to invoke, so this is empty
BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t
, std::size_t, std::size_t, Iterator const&)
{
return pass_flags::pass_normal; // always accept
}
std::size_t get_state() const { return 0; }
void set_state(std::size_t) {}
void set_end(Iterator const& it) {}
Iterator& get_first() { return first_; }
Iterator const& get_first() const { return first_; }
Iterator const& get_last() const { return last_; }
iterator_range<Iterator> get_value() const
{
return iterator_range<Iterator>(first_, last_);
}
bool has_value() const { return false; }
void reset_value() {}
void reset_bol(bool bol) { bol_ = bol; }
protected:
Iterator& first_;
Iterator last_;
next_token_functor next_token_;
get_state_name_type get_state_name_;
bool bol_; // helper storing whether last character was \n
private:
// silence MSVC warning C4512: assignment operator could not be generated
static_data& operator= (static_data const&);
};
///////////////////////////////////////////////////////////////////////
// doesn't support lexer semantic actions, but supports state
template <typename Iterator, typename TokenValue>
class static_data<Iterator, mpl::false_, mpl::true_, TokenValue>
: public static_data<Iterator, mpl::false_, mpl::false_, TokenValue>
{
protected:
typedef static_data<Iterator, mpl::false_, mpl::false_, TokenValue> base_type;
typedef typename base_type::char_type char_type;
public:
typedef Iterator base_iterator_type;
typedef iterator_range<Iterator> token_value_type;
typedef token_value_type get_value_type;
typedef typename base_type::state_type state_type;
typedef typename base_type::state_name_type state_name_type;
typedef typename base_type::semantic_actions_type
semantic_actions_type;
// initialize the shared data
template <typename IterData>
static_data (IterData const& data, Iterator& first
, Iterator const& last)
: base_type(data, first, last), state_(0)
, num_states_(data.num_states_) {}
// The following functions are used by the implementation of the
// placeholder '_state'.
void set_state_name (char_type const* new_state)
{
std::size_t state_id = lexertl::detail::get_state_id(new_state
, this->get_state_name_, num_states_);
// if the following assertion fires you've probably been using
// a lexer state name which was not defined in your token
// definition
BOOST_ASSERT(state_id != boost::lexer::npos);
if (state_id != boost::lexer::npos)
state_ = state_id;
}
char_type const* get_state_name() const
{
return this->get_state_name_(state_);
}
std::size_t get_state_id(char_type const* state) const
{
return lexertl::detail::get_state_id(state
, this->get_state_name_, num_states_);
}
// the functions next() and get_state() are used by the functor
// implementation below
// The function next() tries to match the next token from the
// underlying input sequence.
std::size_t next(Iterator& end, std::size_t& unique_id, bool& prev_bol)
{
prev_bol = this->bol_;
return this->next_token_(state_, this->bol_, end, this->last_
, unique_id);
}
std::size_t& get_state() { return state_; }
void set_state(std::size_t state) { state_ = state; }
protected:
std::size_t state_;
std::size_t num_states_;
private:
// silence MSVC warning C4512: assignment operator could not be generated
static_data& operator= (static_data const&);
};
///////////////////////////////////////////////////////////////////////
// does support actors, but may have no state
template <typename Iterator, typename HasState, typename TokenValue>
class static_data<Iterator, mpl::true_, HasState, TokenValue>
: public static_data<Iterator, mpl::false_, HasState, TokenValue>
{
public:
typedef semantic_actions<Iterator, HasState, static_data>
semantic_actions_type;
protected:
typedef static_data<Iterator, mpl::false_, HasState, TokenValue>
base_type;
typedef typename base_type::char_type char_type;
typedef typename semantic_actions_type::functor_wrapper_type
functor_wrapper_type;
public:
typedef Iterator base_iterator_type;
typedef TokenValue token_value_type;
typedef TokenValue const& get_value_type;
typedef typename base_type::state_type state_type;
typedef typename base_type::state_name_type state_name_type;
typedef detail::wrap_action<functor_wrapper_type
, Iterator, static_data, std::size_t> wrap_action_type;
template <typename IterData>
static_data (IterData const& data, Iterator& first
, Iterator const& last)
: base_type(data, first, last)
, actions_(data.actions_), hold_()
, value_(iterator_range<Iterator>(first, last))
, has_value_(false)
, has_hold_(false)
{}
// invoke attached semantic actions, if defined
BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t state
, std::size_t& id, std::size_t unique_id, Iterator& end)
{
return actions_.invoke_actions(state, id, unique_id, end, *this);
}
// The function less() is used by the implementation of the support
// function lex::less(). Its functionality is equivalent to flex'
// function yyless(): it returns an iterator positioned to the
// nth input character beyond the current start iterator (i.e. by
// assigning the return value to the placeholder '_end' it is
// possible to return all but the first n characters of the current
// token back to the input stream).
Iterator const& less(Iterator& it, int n)
{
it = this->get_first();
std::advance(it, n);
return it;
}
// The function more() is used by the implementation of the support
// function lex::more(). Its functionality is equivalent to flex'
// function yymore(): it tells the lexer that the next time it
// matches a rule, the corresponding token should be appended onto
// the current token value rather than replacing it.
void more()
{
hold_ = this->get_first();
has_hold_ = true;
}
// The function lookahead() is used by the implementation of the
// support function lex::lookahead. It can be used to implement
// lookahead for lexer engines not supporting constructs like flex'
// a/b (match a, but only when followed by b)
bool lookahead(std::size_t id, std::size_t state = std::size_t(~0))
{
Iterator end = end_;
std::size_t unique_id = boost::lexer::npos;
bool bol = this->bol_;
if (std::size_t(~0) == state)
state = this->state_;
return id == this->next_token_(
state, bol, end, this->get_eoi(), unique_id);
}
// The adjust_start() and revert_adjust_start() are helper
// functions needed to implement the functionality required for
// lex::more(). It is called from the functor body below.
bool adjust_start()
{
if (!has_hold_)
return false;
std::swap(this->get_first(), hold_);
has_hold_ = false;
return true;
}
void revert_adjust_start()
{
// this will be called only if adjust_start above returned true
std::swap(this->get_first(), hold_);
has_hold_ = true;
}
TokenValue const& get_value() const
{
if (!has_value_) {
value_ = iterator_range<Iterator>(this->get_first(), end_);
has_value_ = true;
}
return value_;
}
template <typename Value>
void set_value(Value const& val)
{
value_ = val;
has_value_ = true;
}
void set_end(Iterator const& it)
{
end_ = it;
}
bool has_value() const { return has_value_; }
void reset_value() { has_value_ = false; }
protected:
semantic_actions_type const& actions_;
Iterator hold_; // iterator needed to support lex::more()
Iterator end_; // iterator pointing to end of matched token
mutable TokenValue value_; // token value to use
mutable bool has_value_; // 'true' if value_ is valid
bool has_hold_; // 'true' if hold_ is valid
private:
// silence MSVC warning C4512: assignment operator could not be generated
static_data& operator= (static_data const&);
};
///////////////////////////////////////////////////////////////////////
// does support lexer semantic actions, may support state, is used for
// position_token exposing exactly one type
template <typename Iterator, typename HasState, typename TokenValue>
class static_data<Iterator, mpl::true_, HasState, boost::optional<TokenValue> >
: public static_data<Iterator, mpl::false_, HasState, TokenValue>
{
public:
typedef semantic_actions<Iterator, HasState, static_data>
semantic_actions_type;
protected:
typedef static_data<Iterator, mpl::false_, HasState, TokenValue>
base_type;
typedef typename base_type::char_type char_type;
typedef typename semantic_actions_type::functor_wrapper_type
functor_wrapper_type;
public:
typedef Iterator base_iterator_type;
typedef boost::optional<TokenValue> token_value_type;
typedef boost::optional<TokenValue> const& get_value_type;
typedef typename base_type::state_type state_type;
typedef typename base_type::state_name_type state_name_type;
typedef detail::wrap_action<functor_wrapper_type
, Iterator, static_data, std::size_t> wrap_action_type;
template <typename IterData>
static_data (IterData const& data_, Iterator& first, Iterator const& last)
: base_type(data_, first, last)
, actions_(data_.actions_), hold_()
, has_value_(false), has_hold_(false)
{
spirit::traits::assign_to(first, last, value_);
has_value_ = true;
}
// invoke attached semantic actions, if defined
BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t state
, std::size_t& id, std::size_t unique_id, Iterator& end)
{
return actions_.invoke_actions(state, id, unique_id, end, *this);
}
// The function less() is used by the implementation of the support
// function lex::less(). Its functionality is equivalent to flex'
// function yyless(): it returns an iterator positioned to the
// nth input character beyond the current start iterator (i.e. by
// assigning the return value to the placeholder '_end' it is
// possible to return all but the first n characters of the current
// token back to the input stream).
Iterator const& less(Iterator& it, int n)
{
it = this->get_first();
std::advance(it, n);
return it;
}
// The function more() is used by the implementation of the support
// function lex::more(). Its functionality is equivalent to flex'
// function yymore(): it tells the lexer that the next time it
// matches a rule, the corresponding token should be appended onto
// the current token value rather than replacing it.
void more()
{
hold_ = this->get_first();
has_hold_ = true;
}
// The function lookahead() is used by the implementation of the
// support function lex::lookahead. It can be used to implement
// lookahead for lexer engines not supporting constructs like flex'
// a/b (match a, but only when followed by b)
bool lookahead(std::size_t id, std::size_t state = std::size_t(~0))
{
Iterator end = end_;
std::size_t unique_id = boost::lexer::npos;
bool bol = this->bol_;
if (std::size_t(~0) == state)
state = this->state_;
return id == this->next_token_(
state, bol, end, this->get_eoi(), unique_id);
}
// The adjust_start() and revert_adjust_start() are helper
// functions needed to implement the functionality required for
// lex::more(). It is called from the functor body below.
bool adjust_start()
{
if (!has_hold_)
return false;
std::swap(this->get_first(), hold_);
has_hold_ = false;
return true;
}
void revert_adjust_start()
{
// this will be called only if adjust_start above returned true
std::swap(this->get_first(), hold_);
has_hold_ = true;
}
TokenValue const& get_value() const
{
if (!has_value_) {
spirit::traits::assign_to(this->get_first(), end_, value_);
has_value_ = true;
}
return value_;
}
template <typename Value>
void set_value(Value const& val)
{
value_ = val;
has_value_ = true;
}
void set_end(Iterator const& it)
{
end_ = it;
}
bool has_value() const { return has_value_; }
void reset_value() { has_value_ = false; }
protected:
semantic_actions_type const& actions_;
Iterator hold_; // iterator needed to support lex::more()
Iterator end_; // iterator pointing to end of matched token
mutable token_value_type value_; // token value to use
mutable bool has_value_; // 'true' if value_ is valid
bool has_hold_; // 'true' if hold_ is valid
private:
// silence MSVC warning C4512: assignment operator could not be generated
static_data& operator= (static_data const&);
};
}
}}}}
#endif
@@ -0,0 +1,279 @@
// 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_STATIC_LEXER_FEB_10_2008_0753PM)
#define BOOST_SPIRIT_LEX_STATIC_LEXER_FEB_10_2008_0753PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/lexer/lexertl/token.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/functor.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/static_functor_data.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/iterator.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/static_version.hpp>
#if defined(BOOST_SPIRIT_DEBUG)
#include <boost/spirit/home/support/detail/lexer/debug.hpp>
#endif
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
///////////////////////////////////////////////////////////////////////////
// forward declaration
///////////////////////////////////////////////////////////////////////////
namespace static_
{
struct lexer;
}
///////////////////////////////////////////////////////////////////////////
//
// Every lexer type to be used as a lexer for Spirit has to conform to
// the following public interface:
//
// typedefs:
// iterator_type The type of the iterator exposed by this lexer.
// token_type The type of the tokens returned from the exposed
// iterators.
//
// functions:
// default constructor
// Since lexers are instantiated as base classes
// only it might be a good idea to make this
// constructor protected.
// begin, end Return a pair of iterators, when dereferenced
// returning the sequence of tokens recognized in
// the input stream given as the parameters to the
// begin() function.
// add_token Should add the definition of a token to be
// recognized by this lexer.
// clear Should delete all current token definitions
// associated with the given state of this lexer
// object.
//
// template parameters:
// Token The type of the tokens to be returned from the
// exposed token iterator.
// LexerTables See explanations below.
// Iterator The type of the iterator used to access the
// underlying character stream.
// Functor The type of the InputPolicy to use to instantiate
// the multi_pass iterator type to be used as the
// token iterator (returned from begin()/end()).
//
// Additionally, this implementation of a static lexer has a template
// parameter LexerTables allowing to customize the static lexer tables
// to be used. The LexerTables is expected to be a type exposing
// the following functions:
//
// static std::size_t const state_count()
//
// This function needs toreturn the number of lexer states
// contained in the table returned from the state_names()
// function.
//
// static char const* const* state_names()
//
// This function needs to return a pointer to a table of
// names of all lexer states. The table needs to have as
// much entries as the state_count() function returns
//
// template<typename Iterator>
// std::size_t next(std::size_t &start_state_, Iterator const& start_
// , Iterator &start_token_, Iterator const& end_
// , std::size_t& unique_id_);
//
// This function is expected to return the next matched
// token from the underlying input stream.
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//
// The static_lexer class is a implementation of a Spirit.Lex
// lexer on top of Ben Hanson's lexertl library (For more information
// about lexertl go here: http://www.benhanson.net/lexertl.html).
//
// This class is designed to be used in conjunction with a generated,
// static lexer. For more information see the documentation (The Static
// Lexer Model).
//
// This class is supposed to be used as the first and only template
// parameter while instantiating instances of a lex::lexer class.
//
///////////////////////////////////////////////////////////////////////////
template <typename Token = token<>
, typename LexerTables = static_::lexer
, typename Iterator = typename Token::iterator_type
, typename Functor = functor<Token, detail::static_data, Iterator> >
class static_lexer
{
private:
struct dummy { void true_() {} };
typedef void (dummy::*safe_bool)();
public:
// object is always valid
operator safe_bool() const { return &dummy::true_; }
typedef typename boost::detail::iterator_traits<Iterator>::value_type
char_type;
typedef std::basic_string<char_type> string_type;
// Every lexer type to be used as a lexer for Spirit has to conform to
// a public interface
typedef Token token_type;
typedef typename Token::id_type id_type;
typedef iterator<Functor> iterator_type;
private:
// this type is purely used for the iterator_type construction below
struct iterator_data_type
{
typedef typename Functor::next_token_functor next_token_functor;
typedef typename Functor::semantic_actions_type semantic_actions_type;
typedef typename Functor::get_state_name_type get_state_name_type;
iterator_data_type(next_token_functor next
, semantic_actions_type const& actions
, get_state_name_type get_state_name, std::size_t num_states
, bool bol)
: next_(next), actions_(actions), get_state_name_(get_state_name)
, num_states_(num_states), bol_(bol)
{}
next_token_functor next_;
semantic_actions_type const& actions_;
get_state_name_type get_state_name_;
std::size_t num_states_;
bool bol_;
private:
// silence MSVC warning C4512: assignment operator could not be generated
iterator_data_type& operator= (iterator_data_type const&);
};
typedef LexerTables tables_type;
// The following static assertion fires if the referenced static lexer
// tables are generated by a different static lexer version as used for
// the current compilation unit. Please regenerate your static lexer
// tables before trying to create a static_lexer<> instance.
BOOST_SPIRIT_ASSERT_MSG(
tables_type::static_version == SPIRIT_STATIC_LEXER_VERSION
, incompatible_static_lexer_version, (LexerTables));
public:
// Return the start iterator usable for iterating over the generated
// tokens, the generated function next_token(...) is called to match
// the next token from the input.
template <typename Iterator_>
iterator_type begin(Iterator_& first, Iterator_ const& last
, char_type const* initial_state = 0) const
{
iterator_data_type iterator_data(
&tables_type::template next<Iterator_>, actions_
, &tables_type::state_name, tables_type::state_count()
, tables_type::supports_bol
);
return iterator_type(iterator_data, first, last, initial_state);
}
// Return the end iterator usable to stop iterating over the generated
// tokens.
iterator_type end() const
{
return iterator_type();
}
protected:
// Lexer instances can be created by means of a derived class only.
static_lexer(unsigned int) : unique_id_(0) {}
public:
// interface for token definition management
std::size_t add_token (char_type const*, char_type, std::size_t
, char_type const*)
{
return unique_id_++;
}
std::size_t add_token (char_type const*, string_type const&
, std::size_t, char_type const*)
{
return unique_id_++;
}
// interface for pattern definition management
void add_pattern (char_type const*, string_type const&
, string_type const&) {}
void clear(char_type const*) {}
std::size_t add_state(char_type const* state)
{
return detail::get_state_id(state, &tables_type::state_name
, tables_type::state_count());
}
string_type initial_state() const
{
return tables_type::state_name(0);
}
// register a semantic action with the given id
template <typename F>
void add_action(id_type unique_id, std::size_t state, F act)
{
typedef typename Functor::wrap_action_type wrapper_type;
actions_.add_action(unique_id, state, wrapper_type::call(act));
}
bool init_dfa(bool minimize = false) const { return true; }
private:
typename Functor::semantic_actions_type actions_;
std::size_t unique_id_;
};
///////////////////////////////////////////////////////////////////////////
//
// The static_actor_lexer class is another implementation of a
// Spirit.Lex lexer on top of Ben Hanson's lexertl library as outlined
// above (For more information about lexertl go here:
// http://www.benhanson.net/lexertl.html).
//
// Just as the static_lexer class it is meant to be used with
// a statically generated lexer as outlined above.
//
// The only difference to the static_lexer class above is that
// token_def definitions may have semantic (lexer) actions attached while
// being defined:
//
// int w;
// token_def<> word = "[^ \t\n]+";
// self = word[++ref(w)]; // see example: word_count_lexer
//
// This class is supposed to be used as the first and only template
// parameter while instantiating instances of a lex::lexer class.
//
///////////////////////////////////////////////////////////////////////////
template <typename Token = token<>
, typename LexerTables = static_::lexer
, typename Iterator = typename Token::iterator_type
, typename Functor
= functor<Token, detail::static_data, Iterator, mpl::true_> >
class static_actor_lexer
: public static_lexer<Token, LexerTables, Iterator, Functor>
{
protected:
// Lexer instances can be created by means of a derived class only.
static_actor_lexer(unsigned int flags)
: static_lexer<Token, LexerTables, Iterator, Functor>(flags)
{}
};
}}}}
#endif
@@ -0,0 +1,20 @@
// 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_STATIC_LEXER_VERSION_SEP_10_2009_0811PM)
#define BOOST_SPIRIT_LEX_STATIC_LEXER_VERSION_SEP_10_2009_0811PM
#if defined(_MSC_VER)
#pragma once
#endif
///////////////////////////////////////////////////////////////////////////////
// This is the version of the static lexer format. It is used to ensure a
// static lexer has been generated using the same data format as expected
// by the executing application.
///////////////////////////////////////////////////////////////////////////////
#define SPIRIT_STATIC_LEXER_VERSION 0x010000
#endif
@@ -0,0 +1,650 @@
// 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_TOKEN_FEB_10_2008_0751PM)
#define BOOST_SPIRIT_LEX_TOKEN_FEB_10_2008_0751PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/spirit/home/qi/detail/assign_to.hpp>
#include <boost/spirit/home/support/attributes.hpp>
#include <boost/spirit/home/support/argument.hpp>
#include <boost/spirit/home/support/detail/lexer/generator.hpp>
#include <boost/spirit/home/support/detail/lexer/rules.hpp>
#include <boost/spirit/home/support/detail/lexer/consts.hpp>
#include <boost/spirit/home/support/utree/utree_traits_fwd.hpp>
#include <boost/spirit/home/lex/lexer/terminals.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/fusion/include/value_at.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/begin.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/static_assert.hpp>
#if defined(BOOST_SPIRIT_DEBUG)
#include <iosfwd>
#endif
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
///////////////////////////////////////////////////////////////////////////
//
// The token is the type of the objects returned by default by the
// iterator.
//
// template parameters:
// Iterator The type of the iterator used to access the
// underlying character stream.
// AttributeTypes A mpl sequence containing the types of all
// required different token values to be supported
// by this token type.
// HasState A mpl::bool_ indicating, whether this token type
// should support lexer states.
// Idtype The type to use for the token id (defaults to
// std::size_t).
//
// It is possible to use other token types with the spirit::lex
// framework as well. If you plan to use a different type as your token
// type, you'll need to expose the following things from your token type
// to make it compatible with spirit::lex:
//
// typedefs
// iterator_type The type of the iterator used to access the
// underlying character stream.
//
// id_type The type of the token id used.
//
// methods
// default constructor
// This should initialize the token as an end of
// input token.
// constructors The prototype of the other required
// constructors should be:
//
// token(int)
// This constructor should initialize the token as
// an invalid token (not carrying any specific
// values)
//
// where: the int is used as a tag only and its value is
// ignored
//
// and:
//
// token(Idtype id, std::size_t state,
// iterator_type first, iterator_type last);
//
// where: id: token id
// state: lexer state this token was matched in
// first, last: pair of iterators marking the matched
// range in the underlying input stream
//
// accessors
// id() return the token id of the matched input sequence
// id(newid) set the token id of the token instance
//
// state() return the lexer state this token was matched in
//
// value() return the token value
//
// Additionally, you will have to implement a couple of helper functions
// in the same namespace as the token type: a comparison operator==() to
// compare your token instances, a token_is_valid() function and different
// specializations of the Spirit customization point
// assign_to_attribute_from_value as shown below.
//
///////////////////////////////////////////////////////////////////////////
template <typename Iterator = char const*
, typename AttributeTypes = mpl::vector0<>
, typename HasState = mpl::true_
, typename Idtype = std::size_t>
struct token;
///////////////////////////////////////////////////////////////////////////
// This specialization of the token type doesn't contain any item data and
// doesn't support working with lexer states.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Idtype>
struct token<Iterator, lex::omit, mpl::false_, Idtype>
{
typedef Iterator iterator_type;
typedef mpl::false_ has_state;
typedef Idtype id_type;
typedef unused_type token_value_type;
// default constructed tokens correspond to EOI tokens
token() : id_(id_type(boost::lexer::npos)) {}
// construct an invalid token
explicit token(int) : id_(id_type(0)) {}
token(id_type id, std::size_t) : id_(id) {}
token(id_type id, std::size_t, token_value_type)
: id_(id) {}
token_value_type& value() { static token_value_type u; return u; }
token_value_type const& value() const { return unused; }
#if defined(BOOST_SPIRIT_DEBUG)
token(id_type id, std::size_t, Iterator const& first
, Iterator const& last)
: matched_(first, last)
, id_(id) {}
#else
token(id_type id, std::size_t, Iterator const&, Iterator const&)
: id_(id) {}
#endif
// this default conversion operator is needed to allow the direct
// usage of tokens in conjunction with the primitive parsers defined
// in Qi
operator id_type() const { return id_; }
// Retrieve or set the token id of this token instance.
id_type id() const { return id_; }
void id(id_type newid) { id_ = newid; }
std::size_t state() const { return 0; } // always '0' (INITIAL state)
bool is_valid() const
{
return 0 != id_ && id_type(boost::lexer::npos) != id_;
}
#if defined(BOOST_SPIRIT_DEBUG)
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
// workaround for MSVC10 which has problems copying a default
// constructed iterator_range
token& operator= (token const& rhs)
{
if (this != &rhs)
{
id_ = rhs.id_;
if (is_valid())
matched_ = rhs.matched_;
}
return *this;
}
#endif
std::pair<Iterator, Iterator> matched_;
#endif
protected:
id_type id_; // token id, 0 if nothing has been matched
};
#if defined(BOOST_SPIRIT_DEBUG)
template <typename Char, typename Traits, typename Iterator
, typename AttributeTypes, typename HasState, typename Idtype>
inline std::basic_ostream<Char, Traits>&
operator<< (std::basic_ostream<Char, Traits>& os
, token<Iterator, AttributeTypes, HasState, Idtype> const& t)
{
if (t.is_valid()) {
Iterator end = t.matched_.second;
for (Iterator it = t.matched_.first; it != end; ++it)
os << *it;
}
else {
os << "<invalid token>";
}
return os;
}
#endif
///////////////////////////////////////////////////////////////////////////
// This specialization of the token type doesn't contain any item data but
// supports working with lexer states.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Idtype>
struct token<Iterator, lex::omit, mpl::true_, Idtype>
: token<Iterator, lex::omit, mpl::false_, Idtype>
{
private:
typedef token<Iterator, lex::omit, mpl::false_, Idtype> base_type;
public:
typedef typename base_type::id_type id_type;
typedef Iterator iterator_type;
typedef mpl::true_ has_state;
typedef unused_type token_value_type;
// default constructed tokens correspond to EOI tokens
token() : state_(boost::lexer::npos) {}
// construct an invalid token
explicit token(int) : base_type(0), state_(boost::lexer::npos) {}
token(id_type id, std::size_t state)
: base_type(id, boost::lexer::npos), state_(state) {}
token(id_type id, std::size_t state, token_value_type)
: base_type(id, boost::lexer::npos, unused)
, state_(state) {}
token(id_type id, std::size_t state
, Iterator const& first, Iterator const& last)
: base_type(id, boost::lexer::npos, first, last)
, state_(state) {}
std::size_t state() const { return state_; }
#if defined(BOOST_SPIRIT_DEBUG) && BOOST_WORKAROUND(BOOST_MSVC, == 1600)
// workaround for MSVC10 which has problems copying a default
// constructed iterator_range
token& operator= (token const& rhs)
{
if (this != &rhs)
{
this->base_type::operator=(static_cast<base_type const&>(rhs));
state_ = rhs.state_;
}
return *this;
}
#endif
protected:
std::size_t state_; // lexer state this token was matched in
};
///////////////////////////////////////////////////////////////////////////
// The generic version of the token type derives from the
// specialization above and adds a single data member holding the item
// data carried by the token instance.
///////////////////////////////////////////////////////////////////////////
namespace detail
{
///////////////////////////////////////////////////////////////////////
// Meta-function to calculate the type of the variant data item to be
// stored with each token instance.
//
// Note: The iterator pair needs to be the first type in the list of
// types supported by the generated variant type (this is being
// used to identify whether the stored data item in a particular
// token instance needs to be converted from the pair of
// iterators (see the first of the assign_to_attribute_from_value
// specializations below).
///////////////////////////////////////////////////////////////////////
template <typename IteratorPair, typename AttributeTypes>
struct token_value_typesequence
{
typedef typename mpl::insert<
AttributeTypes
, typename mpl::begin<AttributeTypes>::type
, IteratorPair
>::type sequence_type;
typedef typename make_variant_over<sequence_type>::type type;
};
///////////////////////////////////////////////////////////////////////
// The type of the data item stored with a token instance is defined
// by the template parameter 'AttributeTypes' and may be:
//
// lex::omit: no data item is stored with the token
// instance (this is handled by the
// specializations of the token class
// below)
// mpl::vector0<>: each token instance stores a pair of
// iterators pointing to the matched input
// sequence
// mpl::vector<...>: each token instance stores a variant being
// able to store the pair of iterators pointing
// to the matched input sequence, or any of the
// types a specified in the mpl::vector<>
//
// All this is done to ensure the token type is as small (in terms
// of its byte-size) as possible.
///////////////////////////////////////////////////////////////////////
template <typename IteratorPair, typename AttributeTypes>
struct token_value_type
: mpl::eval_if<
mpl::or_<
is_same<AttributeTypes, mpl::vector0<> >
, is_same<AttributeTypes, mpl::vector<> > >
, mpl::identity<IteratorPair>
, token_value_typesequence<IteratorPair, AttributeTypes> >
{};
}
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype>
struct token : token<Iterator, lex::omit, HasState, Idtype>
{
private: // precondition assertions
BOOST_STATIC_ASSERT((mpl::is_sequence<AttributeTypes>::value ||
is_same<AttributeTypes, lex::omit>::value));
typedef token<Iterator, lex::omit, HasState, Idtype> base_type;
protected:
// If no additional token value types are given, the token will
// hold the plain pair of iterators pointing to the matched range
// in the underlying input sequence. Otherwise the token value is
// stored as a variant and will again hold the pair of iterators but
// is able to hold any of the given data types as well. The conversion
// from the iterator pair to the required data type is done when it is
// accessed for the first time.
typedef iterator_range<Iterator> iterpair_type;
public:
typedef typename base_type::id_type id_type;
typedef typename detail::token_value_type<
iterpair_type, AttributeTypes
>::type token_value_type;
typedef Iterator iterator_type;
// default constructed tokens correspond to EOI tokens
token() : value_(iterpair_type(iterator_type(), iterator_type())) {}
// construct an invalid token
explicit token(int)
: base_type(0)
, value_(iterpair_type(iterator_type(), iterator_type())) {}
token(id_type id, std::size_t state, token_value_type const& value)
: base_type(id, state, value)
, value_(value) {}
token(id_type id, std::size_t state, Iterator const& first
, Iterator const& last)
: base_type(id, state, first, last)
, value_(iterpair_type(first, last)) {}
token_value_type& value() { return value_; }
token_value_type const& value() const { return value_; }
#if BOOST_WORKAROUND(BOOST_MSVC, == 1600)
// workaround for MSVC10 which has problems copying a default
// constructed iterator_range
token& operator= (token const& rhs)
{
if (this != &rhs)
{
this->base_type::operator=(static_cast<base_type const&>(rhs));
if (this->is_valid())
value_ = rhs.value_;
}
return *this;
}
#endif
protected:
token_value_type value_; // token value, by default a pair of iterators
};
///////////////////////////////////////////////////////////////////////////
// tokens are considered equal, if their id's match (these are unique)
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype>
inline bool
operator== (token<Iterator, AttributeTypes, HasState, Idtype> const& lhs,
token<Iterator, AttributeTypes, HasState, Idtype> const& rhs)
{
return lhs.id() == rhs.id();
}
///////////////////////////////////////////////////////////////////////////
// This overload is needed by the multi_pass/functor_input_policy to
// validate a token instance. It has to be defined in the same namespace
// as the token class itself to allow ADL to find it.
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype>
inline bool
token_is_valid(token<Iterator, AttributeTypes, HasState, Idtype> const& t)
{
return t.is_valid();
}
}}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
// We have to provide specializations for the customization point
// assign_to_attribute_from_value allowing to extract the needed value
// from the token.
///////////////////////////////////////////////////////////////////////////
// This is called from the parse function of token_def if the token_def
// has been defined to carry a special attribute type
template <typename Attribute, typename Iterator, typename AttributeTypes
, typename HasState, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
{
static void
call(lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> const& t
, Attribute& attr)
{
// The goal of this function is to avoid the conversion of the pair of
// iterators (to the matched character sequence) into the token value
// of the required type being done more than once. For this purpose it
// checks whether the stored value type is still the default one (pair
// of iterators) and if yes, replaces the pair of iterators with the
// converted value to be returned from subsequent calls.
if (0 == t.value().which()) {
// first access to the token value
typedef iterator_range<Iterator> iterpair_type;
iterpair_type const& ip = boost::get<iterpair_type>(t.value());
// Interestingly enough we use the assign_to() framework defined in
// Spirit.Qi allowing to convert the pair of iterators to almost any
// required type (assign_to(), if available, uses the standard Spirit
// parsers to do the conversion).
spirit::traits::assign_to(ip.begin(), ip.end(), attr);
// If you get an error during the compilation of the following
// assignment expression, you probably forgot to list one or more
// types used as token value types (in your token_def<...>
// definitions) in your definition of the token class. I.e. any token
// value type used for a token_def<...> definition has to be listed
// during the declaration of the token type to use. For instance let's
// assume we have two token_def's:
//
// token_def<int> number; number = "...";
// token_def<std::string> identifier; identifier = "...";
//
// Then you'll have to use the following token type definition
// (assuming you are using the token class):
//
// typedef mpl::vector<int, std::string> token_values;
// typedef token<base_iter_type, token_values> token_type;
//
// where: base_iter_type is the iterator type used to expose the
// underlying input stream.
//
// This token_type has to be used as the second template parameter
// to the lexer class:
//
// typedef lexer<base_iter_type, token_type> lexer_type;
//
// again, assuming you're using the lexer<> template for your
// tokenization.
typedef lex::lexertl::token<
Iterator, AttributeTypes, HasState, Idtype> token_type;
spirit::traits::assign_to(
attr, const_cast<token_type&>(t).value()); // re-assign value
}
else {
// reuse the already assigned value
spirit::traits::assign_to(boost::get<Attribute>(t.value()), attr);
}
}
};
template <typename Attribute, typename Iterator, typename AttributeTypes
, typename HasState, typename Idtype>
struct assign_to_container_from_value<Attribute
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
: assign_to_attribute_from_value<Attribute
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
{};
template <typename Iterator, typename AttributeTypes
, typename HasState, typename Idtype>
struct assign_to_container_from_value<utree
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
: assign_to_attribute_from_value<utree
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
{};
template <typename Iterator>
struct assign_to_container_from_value<
iterator_range<Iterator>, iterator_range<Iterator> >
{
static void
call(iterator_range<Iterator> const& val, iterator_range<Iterator>& attr)
{
attr = val;
}
};
// These are called from the parse function of token_def if the token type
// has no special attribute type assigned
template <typename Attribute, typename Iterator, typename HasState
, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
{
static void
call(lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> const& t
, Attribute& attr)
{
// The default type returned by the token_def parser component (if
// it has no token value type assigned) is the pair of iterators
// to the matched character sequence.
spirit::traits::assign_to(t.value().begin(), t.value().end(), attr);
}
};
// template <typename Attribute, typename Iterator, typename HasState
// , typename Idtype>
// struct assign_to_container_from_value<Attribute
// , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
// : assign_to_attribute_from_value<Attribute
// , lex::lexertl::token<Iterator, mpl::vector0<>, HasState, Idtype> >
// {};
// same as above but using mpl::vector<> instead of mpl::vector0<>
template <typename Attribute, typename Iterator, typename HasState
, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
{
static void
call(lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> const& t
, Attribute& attr)
{
// The default type returned by the token_def parser component (if
// it has no token value type assigned) is the pair of iterators
// to the matched character sequence.
spirit::traits::assign_to(t.value().begin(), t.value().end(), attr);
}
};
// template <typename Attribute, typename Iterator, typename HasState
// , typename Idtype>
// struct assign_to_container_from_value<Attribute
// , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
// : assign_to_attribute_from_value<Attribute
// , lex::lexertl::token<Iterator, mpl::vector<>, HasState, Idtype> >
// {};
// This is called from the parse function of token_def if the token type
// has been explicitly omitted (i.e. no attribute value is used), which
// essentially means that every attribute gets initialized using default
// constructed values.
template <typename Attribute, typename Iterator, typename HasState
, typename Idtype>
struct assign_to_attribute_from_value<Attribute
, lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
{
static void
call(lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> const& t
, Attribute& attr)
{
// do nothing
}
};
template <typename Attribute, typename Iterator, typename HasState
, typename Idtype>
struct assign_to_container_from_value<Attribute
, lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
: assign_to_attribute_from_value<Attribute
, lex::lexertl::token<Iterator, lex::omit, HasState, Idtype> >
{};
// This is called from the parse function of lexer_def_
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype_, typename Idtype>
struct assign_to_attribute_from_value<
fusion::vector2<Idtype_, iterator_range<Iterator> >
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
{
static void
call(lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> const& t
, fusion::vector2<Idtype_, iterator_range<Iterator> >& attr)
{
// The type returned by the lexer_def_ parser components is a
// fusion::vector containing the token id of the matched token
// and the pair of iterators to the matched character sequence.
typedef iterator_range<Iterator> iterpair_type;
typedef fusion::vector2<Idtype_, iterator_range<Iterator> >
attribute_type;
iterpair_type const& ip = boost::get<iterpair_type>(t.value());
attr = attribute_type(t.id(), ip);
}
};
template <typename Iterator, typename AttributeTypes, typename HasState
, typename Idtype_, typename Idtype>
struct assign_to_container_from_value<
fusion::vector2<Idtype_, iterator_range<Iterator> >
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
: assign_to_attribute_from_value<
fusion::vector2<Idtype_, iterator_range<Iterator> >
, lex::lexertl::token<Iterator, AttributeTypes, HasState, Idtype> >
{};
///////////////////////////////////////////////////////////////////////////
// Overload debug output for a single token, this integrates lexer tokens
// with Qi's simple_trace debug facilities
template <typename Iterator, typename Attribute, typename HasState
, typename Idtype>
struct token_printer_debug<
lex::lexertl::token<Iterator, Attribute, HasState, Idtype> >
{
typedef lex::lexertl::token<Iterator, Attribute, HasState, Idtype> token_type;
template <typename Out>
static void print(Out& out, token_type const& val)
{
out << '[';
spirit::traits::print_token(out, val.value());
out << ']';
}
};
}}}
#endif
@@ -0,0 +1,154 @@
/*=============================================================================
Copyright (c) 2001-2011 Joel de Guzman
Copyright (c) 2001-2011 Hartmut Kaiser
http://spirit.sourceforge.net/
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_WRAP_ACTION_APR_19_2008_0103PM)
#define BOOST_SPIRIT_WRAP_ACTION_APR_19_2008_0103PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_scope.hpp>
#include <boost/spirit/home/support/attributes.hpp>
#include <boost/spirit/home/lex/lexer/pass_flags.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace lex { namespace lexertl
{
namespace detail
{
template <typename FunctionType, typename Iterator, typename Context
, typename IdType>
struct wrap_action
{
// plain functions with 5 arguments, function objects (including
// phoenix actors) are not touched at all
template <typename F>
static FunctionType call(F const& f)
{
return f;
}
// semantic actions with 4 arguments
template <typename F>
static void arg4_action(F* f, Iterator& start, Iterator& end
, BOOST_SCOPED_ENUM(pass_flags)& pass, IdType& id
, Context const&)
{
f(start, end, pass, id);
}
template <typename A0, typename A1, typename A2, typename A3>
static FunctionType call(void (*f)(A0, A1, A2, A3))
{
void (*pf)(void(*)(A0, A1, A2, A3)
, Iterator&, Iterator&, BOOST_SCOPED_ENUM(pass_flags)&
, IdType&, Context const&) = &wrap_action::arg4_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
using phoenix::arg_names::_5;
return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
}
// semantic actions with 3 arguments
template <typename F>
static void arg3_action(F* f, Iterator& start, Iterator& end
, BOOST_SCOPED_ENUM(pass_flags)& pass, IdType
, Context const&)
{
f(start, end, pass);
}
template <typename A0, typename A1, typename A2>
static FunctionType call(void (*f)(A0, A1, A2))
{
void (*pf)(void(*)(A0, A1, A2), Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&, IdType
, Context const&) = &wrap_action::arg3_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
using phoenix::arg_names::_5;
return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
}
// semantic actions with 2 arguments
template <typename F>
static void arg2_action(F* f, Iterator& start, Iterator& end
, BOOST_SCOPED_ENUM(pass_flags)&, IdType, Context const&)
{
f (start, end);
}
template <typename A0, typename A1>
static FunctionType call(void (*f)(A0, A1))
{
void (*pf)(void(*)(A0, A1), Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&
, IdType, Context const&) = &wrap_action::arg2_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
using phoenix::arg_names::_5;
return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
}
// we assume that either both iterators are to be passed to the
// semantic action or none iterator at all (i.e. it's not possible
// to have a lexer semantic action function taking one arguments).
// semantic actions with 0 argument
template <typename F>
static void arg0_action(F* f, Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&, IdType, Context const&)
{
f();
}
static FunctionType call(void (*f)())
{
void (*pf)(void(*)(), Iterator&, Iterator&
, BOOST_SCOPED_ENUM(pass_flags)&
, IdType, Context const&) = &arg0_action;
using phoenix::arg_names::_1;
using phoenix::arg_names::_2;
using phoenix::arg_names::_3;
using phoenix::arg_names::_4;
using phoenix::arg_names::_5;
return phoenix::bind(pf, f, _1, _2, _3, _4, _5);
}
};
// specialization allowing to skip wrapping for lexer types not
// supporting semantic actions
template <typename Iterator, typename Context, typename Idtype>
struct wrap_action<unused_type, Iterator, Context, Idtype>
{
// plain function objects are not touched at all
template <typename F>
static F const& call(F const& f)
{
return f;
}
};
}
}}}}
#endif
@@ -0,0 +1,28 @@
// 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_PASS_FLAGS_JUN_09_2009_0840PM)
#define BOOST_SPIRIT_LEX_PASS_FLAGS_JUN_09_2009_0840PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
BOOST_SCOPED_ENUM_START(pass_flags)
{
pass_fail = 0, // make the current match fail in retrospective
pass_normal = 1, // continue normal token matching, that's the default
pass_ignore = 2 // ignore the current token and start matching the next
};
BOOST_SCOPED_ENUM_END
}}}
#endif
@@ -0,0 +1,72 @@
// 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(SPIRIT_LEX_SEQUENCE_MAR_28_2007_0610PM)
#define SPIRIT_LEX_SEQUENCE_MAR_28_2007_0610PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/domain.hpp>
#include <boost/spirit/home/lex/lexer_type.hpp>
#include <boost/spirit/home/lex/meta_compiler.hpp>
#include <boost/spirit/home/lex/detail/sequence_function.hpp>
#include <boost/fusion/include/any.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
template <>
struct use_operator<lex::domain, proto::tag::bitwise_or> // enables |
: mpl::true_ {};
template <>
struct flatten_tree<lex::domain, proto::tag::bitwise_or> // flattens |
: mpl::true_ {};
}}
namespace boost { namespace spirit { namespace lex
{
template <typename Elements>
struct sequence : nary_lexer<sequence<Elements> >
{
sequence(Elements const& elements)
: elements(elements) {}
template <typename LexerDef, typename String>
void collect(LexerDef& lexdef, String const& state
, String const& targetstate) const
{
typedef detail::sequence_collect_function<LexerDef, String>
collect_function_type;
collect_function_type f (lexdef, state, targetstate);
fusion::any(elements, f);
}
template <typename LexerDef>
void add_actions(LexerDef& lexdef) const
{
detail::sequence_add_actions_function<LexerDef> f (lexdef);
fusion::any(elements, f);
}
Elements elements;
};
///////////////////////////////////////////////////////////////////////////
// Lexer generator: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Elements, typename Modifiers>
struct make_composite<proto::tag::bitwise_or, Elements, Modifiers>
: make_nary_composite<Elements, sequence>
{};
}}} // namespace boost::spirit::lex
#endif
@@ -0,0 +1,177 @@
// 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_STRING_TOKEN_DEF_MAR_28_2007_0722PM)
#define BOOST_SPIRIT_LEX_STRING_TOKEN_DEF_MAR_28_2007_0722PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/lex/domain.hpp>
#include <boost/spirit/home/lex/lexer_type.hpp>
#include <boost/spirit/home/lex/meta_compiler.hpp>
#include <boost/type_traits/add_const.hpp>
#include <boost/type_traits/add_reference.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables strings
template <typename T>
struct use_terminal<lex::domain, T
, typename enable_if<traits::is_string<T> >::type>
: mpl::true_ {};
// enables string(str)
template <typename CharEncoding, typename A0>
struct use_terminal<lex::domain
, terminal_ex<
tag::char_code<tag::string, CharEncoding>
, fusion::vector1<A0> > >
: traits::is_string<A0> {};
// enables string(str, ID)
template <typename CharEncoding, typename A0, typename A1>
struct use_terminal<lex::domain
, terminal_ex<
tag::char_code<tag::string, CharEncoding>
, fusion::vector2<A0, A1> > >
: traits::is_string<A0> {};
}}
namespace boost { namespace spirit { namespace lex
{
// use string from standard character set by default
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::standard::string;
#endif
using spirit::standard::string_type;
///////////////////////////////////////////////////////////////////////////
//
// string_token_def
// represents a string based token definition
//
///////////////////////////////////////////////////////////////////////////
template <typename String, typename IdType = std::size_t
, typename CharEncoding = char_encoding::standard>
struct string_token_def
: primitive_lexer<string_token_def<String, IdType, CharEncoding> >
{
typedef typename
remove_const<typename traits::char_type_of<String>::type>::type
char_type;
typedef std::basic_string<char_type> string_type;
string_token_def(typename add_reference<String>::type str, IdType const& id)
: str_(str), id_(id), unique_id_(std::size_t(~0))
, token_state_(std::size_t(~0))
{}
template <typename LexerDef, typename String_>
void collect(LexerDef& lexdef, String_ const& state
, String_ const& targetstate) const
{
std::size_t state_id = lexdef.add_state(state.c_str());
// If the following assertion fires you are probably trying to use
// a single string_token_def instance in more than one lexer state.
// This is not possible. Please create a separate token_def instance
// from the same regular expression for each lexer state it needs
// to be associated with.
BOOST_ASSERT(
(std::size_t(~0) == token_state_ || state_id == token_state_) &&
"Can't use single string_token_def with more than one lexer state");
char_type const* target = targetstate.empty() ? 0 : targetstate.c_str();
if (target)
lexdef.add_state(target);
token_state_ = state_id;
if (IdType(~0) == id_)
id_ = IdType(lexdef.get_next_id());
unique_id_ = lexdef.add_token (state.c_str(), str_, id_, target);
}
template <typename LexerDef>
void add_actions(LexerDef&) const {}
std::size_t id() const { return id_; }
std::size_t unique_id() const { return unique_id_; }
std::size_t state() const { return token_state_; }
string_type str_;
mutable IdType id_;
mutable std::size_t unique_id_;
mutable std::size_t token_state_;
};
///////////////////////////////////////////////////////////////////////////
// Lex generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename T, typename Modifiers>
struct make_primitive<T, Modifiers
, typename enable_if<traits::is_string<T> >::type>
{
typedef typename add_const<T>::type const_string;
typedef string_token_def<const_string> result_type;
result_type operator()(
typename add_reference<const_string>::type str, unused_type) const
{
return result_type(str, std::size_t(~0));
}
};
template <typename Modifiers, typename CharEncoding, typename A0>
struct make_primitive<
terminal_ex<
tag::char_code<tag::string, CharEncoding>
, fusion::vector1<A0> >
, Modifiers>
{
typedef typename add_const<A0>::type const_string;
typedef string_token_def<const_string, std::size_t, CharEncoding>
result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args), std::size_t(~0));
}
};
template <typename Modifiers, typename CharEncoding, typename A0, typename A1>
struct make_primitive<
terminal_ex<
tag::char_code<tag::string, CharEncoding>
, fusion::vector2<A0, A1> >
, Modifiers>
{
typedef typename add_const<A0>::type const_string;
typedef string_token_def<const_string, A1, CharEncoding> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(
fusion::at_c<0>(term.args), fusion::at_c<1>(term.args));
}
};
}}} // namespace boost::spirit::lex
#endif
@@ -0,0 +1,205 @@
// 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(SPIRIT_LEX_SUPPORT_FUNCTIONS_JUN_08_2009_0211PM)
#define SPIRIT_LEX_SUPPORT_FUNCTIONS_JUN_08_2009_0211PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/home/support/detail/scoped_enum_emulation.hpp>
#include <boost/spirit/home/lex/lexer/pass_flags.hpp>
#include <boost/spirit/home/lex/lexer/support_functions_expression.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
// The function object less_type is used by the implementation of the
// support function lex::less(). Its functionality is equivalent to flex'
// function yyless(): it returns an iterator positioned to the nth input
// character beyond the current start iterator (i.e. by assigning the
// return value to the placeholder '_end' it is possible to return all but
// the first n characters of the current token back to the input stream.
//
// This Phoenix actor is invoked whenever the function lex::less(n) is
// used inside a lexer semantic action:
//
// lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
// this->self = identifier [ _end = lex::less(4) ];
//
// The example shows how to limit the length of the matched identifier to
// four characters.
//
// Note: the function lex::less() has no effect if used on it's own, you
// need to use the returned result in order to make use of its
// functionality.
template <typename Actor>
struct less_type
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef typename remove_reference<
typename remove_const<
typename mpl::at_c<typename Env::args_type, 4>::type
>::type
>::type context_type;
typedef typename context_type::base_iterator_type type;
};
template <typename Env>
typename result<Env>::type
eval(Env const& env) const
{
typename result<Env>::type it;
return fusion::at_c<4>(env.args()).less(it, actor_());
}
less_type(Actor const& actor)
: actor_(actor) {}
Actor actor_;
};
// The function lex::less() is used to create a Phoenix actor allowing to
// implement functionality similar to flex' function yyless().
template <typename T>
inline typename expression::less<
typename phoenix::as_actor<T>::type
>::type const
less(T const& v)
{
return expression::less<T>::make(phoenix::as_actor<T>::convert(v));
}
///////////////////////////////////////////////////////////////////////////
// The function object more_type is used by the implementation of the
// support function lex::more(). Its functionality is equivalent to flex'
// function yymore(): it tells the lexer that the next time it matches a
// rule, the corresponding token should be appended onto the current token
// value rather than replacing it.
//
// This Phoenix actor is invoked whenever the function lex::more(n) is
// used inside a lexer semantic action:
//
// lex::token_def<> identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
// this->self = identifier [ lex::more() ];
//
// The example shows how prefix the next matched token with the matched
// identifier.
struct more_type
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef void type;
};
template <typename Env>
void eval(Env const& env) const
{
fusion::at_c<4>(env.args()).more();
}
};
// The function lex::more() is used to create a Phoenix actor allowing to
// implement functionality similar to flex' function yymore().
//inline expression::more<mpl::void_>::type const
inline phoenix::actor<more_type> more()
{
return phoenix::actor<more_type>();
}
///////////////////////////////////////////////////////////////////////////
// The function object lookahead_type is used by the implementation of the
// support function lex::lookahead(). Its functionality is needed to
// emulate the flex' lookahead operator a/b. Use lex::lookahead() inside
// of lexer semantic actions to test whether the argument to this function
// matches the current look ahead input. lex::lookahead() can be used with
// either a token id or a token_def instance as its argument. It returns
// a bool indicating whether the look ahead has been matched.
template <typename IdActor, typename StateActor>
struct lookahead_type
{
typedef mpl::true_ no_nullary;
template <typename Env>
struct result
{
typedef bool type;
};
template <typename Env>
bool eval(Env const& env) const
{
return fusion::at_c<4>(env.args()).
lookahead(id_actor_(), state_actor_());
}
lookahead_type(IdActor const& id_actor, StateActor const& state_actor)
: id_actor_(id_actor), state_actor_(state_actor) {}
IdActor id_actor_;
StateActor state_actor_;
};
// The function lex::lookahead() is used to create a Phoenix actor
// allowing to implement functionality similar to flex' lookahead operator
// a/b.
template <typename T>
inline typename expression::lookahead<
typename phoenix::as_actor<T>::type
, typename phoenix::as_actor<std::size_t>::type
>::type const
lookahead(T const& id)
{
typedef typename phoenix::as_actor<T>::type id_actor_type;
typedef typename phoenix::as_actor<std::size_t>::type state_actor_type;
return expression::lookahead<id_actor_type, state_actor_type>::make(
phoenix::as_actor<T>::convert(id),
phoenix::as_actor<std::size_t>::convert(std::size_t(~0)));
}
template <typename Attribute, typename Char, typename Idtype>
inline typename expression::lookahead<
typename phoenix::as_actor<Idtype>::type
, typename phoenix::as_actor<std::size_t>::type
>::type const
lookahead(token_def<Attribute, Char, Idtype> const& tok)
{
typedef typename phoenix::as_actor<Idtype>::type id_actor_type;
typedef typename phoenix::as_actor<std::size_t>::type state_actor_type;
std::size_t state = tok.state();
// The following assertion fires if you pass a token_def instance to
// lex::lookahead without first associating this instance with the
// lexer.
BOOST_ASSERT(std::size_t(~0) != state &&
"token_def instance not associated with lexer yet");
return expression::lookahead<id_actor_type, state_actor_type>::make(
phoenix::as_actor<Idtype>::convert(tok.id()),
phoenix::as_actor<std::size_t>::convert(state));
}
///////////////////////////////////////////////////////////////////////////
inline BOOST_SCOPED_ENUM(pass_flags) ignore()
{
return pass_flags::pass_ignore;
}
}}}
#endif
@@ -0,0 +1,102 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2011 Thomas Heller
//
// 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(SPIRIT_LEX_SUPPORT_FUNCTIONS_EXPRESSION_MAR_22_2011_0711PM)
#define SPIRIT_LEX_SUPPORT_FUNCTIONS_EXPRESSION_MAR_22_2011_0711PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/include/phoenix_core.hpp>
namespace boost { namespace spirit { namespace lex
{
template <typename> struct less_type;
struct more_type;
template <typename, typename> struct lookahead_type;
}}}
///////////////////////////////////////////////////////////////////////////////
BOOST_PHOENIX_DEFINE_EXPRESSION(
(boost)(spirit)(lex)(less)
, (boost::phoenix::meta_grammar)
)
BOOST_PHOENIX_DEFINE_EXPRESSION(
(boost)(spirit)(lex)(lookahead)
, (boost::phoenix::meta_grammar)
(boost::phoenix::meta_grammar)
)
namespace boost { namespace phoenix
{
namespace result_of
{
template <>
struct is_nullary<custom_terminal<boost::spirit::lex::more_type> >
: mpl::false_
{};
}
template <typename Dummy>
struct is_custom_terminal<boost::spirit::lex::more_type, Dummy> : mpl::true_ {};
template <typename Dummy>
struct custom_terminal<boost::spirit::lex::more_type, Dummy>
: proto::call<
v2_eval(
proto::make<boost::spirit::lex::more_type()>
, proto::call<functional::env(proto::_state)>
)
>
{};
template <typename Dummy>
struct is_nullary::when<spirit::lex::rule::less, Dummy>
: proto::make<mpl::false_()>
{};
template <typename Dummy>
struct default_actions::when<spirit::lex::rule::less, Dummy>
: proto::call<
v2_eval(
proto::make<
spirit::lex::less_type<proto::_child0>(proto::_child0)
>
, _env
)
>
{};
template <typename Dummy>
struct is_nullary::when<spirit::lex::rule::lookahead, Dummy>
: proto::make<mpl::false_()>
{};
template <typename Dummy>
struct default_actions::when<spirit::lex::rule::lookahead, Dummy>
: proto::call<
v2_eval(
proto::make<
spirit::lex::lookahead_type<
proto::_child0
, proto::_child1
>(
proto::_child0
, proto::_child1
)
>
, _env
)
>
{};
}}
#endif
@@ -0,0 +1,23 @@
// 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_TERMINALS_APR_20_2009_0550PM)
#define BOOST_SPIRIT_LEX_TERMINALS_APR_20_2009_0550PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/common_terminals.hpp>
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
// Define a more convenient name for an omitted token attribute type
typedef spirit::omit_type omit;
using spirit::omit_type;
}}}
#endif
@@ -0,0 +1,246 @@
// 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_TOKEN_DEF_MAR_13_2007_0145PM)
#define BOOST_SPIRIT_LEX_TOKEN_DEF_MAR_13_2007_0145PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/support/argument.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/qi/skip_over.hpp>
#include <boost/spirit/home/qi/detail/construct.hpp>
#include <boost/spirit/home/qi/detail/assign_to.hpp>
#include <boost/spirit/home/lex/reference.hpp>
#include <boost/spirit/home/lex/lexer_type.hpp>
#include <boost/spirit/home/lex/lexer/terminals.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/mpl/if.hpp>
#include <boost/detail/iterator.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/variant.hpp>
#include <string>
#include <cstdlib>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
#endif
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
// This component represents a token definition
///////////////////////////////////////////////////////////////////////////
template<typename Attribute = unused_type
, typename Char = char
, typename Idtype = std::size_t>
struct token_def
: proto::extends<
typename proto::terminal<
lex::reference<token_def<Attribute, Char, Idtype> const, Idtype>
>::type
, token_def<Attribute, Char, Idtype> >
, qi::parser<token_def<Attribute, Char, Idtype> >
, lex::lexer_type<token_def<Attribute, Char, Idtype> >
{
private:
// initialize proto base class
typedef lex::reference<token_def const, Idtype> reference_;
typedef typename proto::terminal<reference_>::type terminal_type;
typedef proto::extends<terminal_type, token_def> proto_base_type;
static std::size_t const all_states_id = static_cast<std::size_t>(-2);
public:
// Qi interface: meta-function calculating parser return type
template <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 omit has been specified).
typedef typename Iterator::base_iterator_type iterator_type;
typedef typename mpl::if_<
traits::not_is_unused<Attribute>
, typename mpl::if_<
is_same<Attribute, lex::omit>, unused_type, Attribute
>::type
, iterator_range<iterator_type>
>::type type;
};
public:
// 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
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 const& t = *first;
if (token_id_ == t.id() &&
(all_states_id == token_state_ || token_state_ == t.state()))
{
spirit::traits::assign_to(t, attr);
++first;
return true;
}
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
if (0 == def_.which())
return info("token_def", boost::get<string_type>(def_));
return info("token_def", boost::get<char_type>(def_));
}
///////////////////////////////////////////////////////////////////////
// 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
, String const& targetstate) const
{
std::size_t state_id = lexdef.add_state(state.c_str());
// If the following assertion fires you are probably trying to use
// a single token_def instance in more than one lexer state. This
// is not possible. Please create a separate token_def instance
// from the same regular expression for each lexer state it needs
// to be associated with.
BOOST_ASSERT(
(std::size_t(~0) == token_state_ || state_id == token_state_) &&
"Can't use single token_def with more than one lexer state");
char_type const* target = targetstate.empty() ? 0 : targetstate.c_str();
if (target)
lexdef.add_state(target);
token_state_ = state_id;
if (0 == token_id_)
token_id_ = lexdef.get_next_id();
if (0 == def_.which()) {
unique_id_ = lexdef.add_token(state.c_str()
, boost::get<string_type>(def_), token_id_, target);
}
else {
unique_id_ = lexdef.add_token(state.c_str()
, boost::get<char_type>(def_), token_id_, target);
}
}
template <typename LexerDef>
void add_actions(LexerDef&) const {}
public:
typedef Char char_type;
typedef Idtype id_type;
typedef std::basic_string<char_type> string_type;
// Lex interface: constructing token definitions
token_def()
: proto_base_type(terminal_type::make(reference_(*this)))
, def_('\0'), token_id_()
, unique_id_(std::size_t(~0)), token_state_(std::size_t(~0)) {}
token_def(token_def const& rhs)
: proto_base_type(terminal_type::make(reference_(*this)))
, def_(rhs.def_), token_id_(rhs.token_id_)
, unique_id_(rhs.unique_id_), token_state_(rhs.token_state_) {}
explicit token_def(char_type def_, Idtype id_ = Idtype())
: proto_base_type(terminal_type::make(reference_(*this)))
, def_(def_)
, token_id_(Idtype() == id_ ? Idtype(def_) : id_)
, unique_id_(std::size_t(~0)), token_state_(std::size_t(~0)) {}
explicit token_def(string_type const& def_, Idtype id_ = Idtype())
: proto_base_type(terminal_type::make(reference_(*this)))
, def_(def_), token_id_(id_)
, unique_id_(std::size_t(~0)), token_state_(std::size_t(~0)) {}
template <typename String>
token_def& operator= (String const& definition)
{
def_ = definition;
token_id_ = Idtype();
unique_id_ = std::size_t(~0);
token_state_ = std::size_t(~0);
return *this;
}
token_def& operator= (token_def const& rhs)
{
def_ = rhs.def_;
token_id_ = rhs.token_id_;
unique_id_ = rhs.unique_id_;
token_state_ = rhs.token_state_;
return *this;
}
// general accessors
Idtype const& id() const { return token_id_; }
void id(Idtype const& id) { token_id_ = id; }
std::size_t unique_id() const { return unique_id_; }
string_type definition() const
{
return (0 == def_.which()) ?
boost::get<string_type>(def_) :
string_type(1, boost::get<char_type>(def_));
}
std::size_t state() const { return token_state_; }
private:
variant<string_type, char_type> def_;
mutable Idtype token_id_;
mutable std::size_t unique_id_;
mutable std::size_t token_state_;
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template<typename Attribute, typename Char, typename Idtype
, typename Attr, typename Context, typename Iterator>
struct handles_container<
lex::token_def<Attribute, Char, Idtype>, Attr, Context, Iterator>
: traits::is_container<
typename attribute_of<
lex::token_def<Attribute, Char, Idtype>, Context, Iterator
>::type>
{};
}}}
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
#endif
@@ -0,0 +1,18 @@
// 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_LEXERTL_MAR_17_2007_1008PM)
#define BOOST_SPIRIT_LEX_LEXERTL_MAR_17_2007_1008PM
#if defined(_MSC_VER)
#pragma once
#endif
// These includes make available everything needed to use lexertl either
// standalone or as a lexer component for spirit::qi
#include <boost/spirit/home/lex.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/lexer.hpp>
#endif
@@ -0,0 +1,18 @@
// 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_STATIC_LEXERTL_FEB_11_2008_1045AM)
#define BOOST_SPIRIT_LEX_STATIC_LEXERTL_FEB_11_2008_1045AM
#if defined(_MSC_VER)
#pragma once
#endif
// These includes make available everything needed to use lexertl either
// standalone or as a lexer component for spirit::qi
#include <boost/spirit/home/lex.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/static_lexer.hpp>
#endif
@@ -0,0 +1,100 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// 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_LEXER_TYPE_APR_20_2009_0759PM)
#define BOOST_SPIRIT_LEXER_TYPE_APR_20_2009_0759PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/mpl/has_xxx.hpp>
#include <boost/spirit/home/lex/domain.hpp>
namespace boost { namespace spirit { namespace lex
{
template <typename Derived>
struct lexer_type
{
struct lexer_id;
typedef Derived derived_type;
typedef lex::domain domain;
// Requirement: l.collect(def, state, targetstate) -> void
//
// l: a lexer component
// def: token definition container
// state: lexer state this token definition needs to be added to
// targetstate: an optional lexer state the lexer should be switched
// into after matching this token
Derived const& derived() const
{
return *static_cast<Derived const*>(this);
}
};
template <typename Derived>
struct primitive_lexer : lexer_type<Derived>
{
struct primitive_lexer_id;
};
template <typename Derived>
struct unary_lexer : lexer_type<Derived>
{
struct unary_lexer_id;
// Requirement: l.subject -> subject lexer component
//
// l: a unary lexer component
// Requirement: L::subject_type -> subject lexer component type
//
// L: a unary lexer component type
};
template <typename Derived>
struct nary_lexer : lexer_type<Derived>
{
struct nary_lexer_id;
// Requirement: l.elements -> fusion sequence
//
// l: a composite lexer component
// Requirement: L::elements_type -> fusion sequence
//
// L: a composite lexer component type
};
}}}
namespace boost { namespace spirit { namespace traits // classification
{
namespace detail
{
BOOST_MPL_HAS_XXX_TRAIT_DEF(lexer_id)
BOOST_MPL_HAS_XXX_TRAIT_DEF(primitive_lexer_id)
BOOST_MPL_HAS_XXX_TRAIT_DEF(unary_lexer_id)
BOOST_MPL_HAS_XXX_TRAIT_DEF(nary_lexer_id)
}
template <typename T>
struct is_lexer : detail::has_lexer_id<T> {};
template <typename T>
struct is_primitive_lexer : detail::has_primitive_lexer_id<T> {};
template <typename T>
struct is_unary_lexer : detail::has_unary_lexer_id<T> {};
template <typename T>
struct is_nary_lexer : detail::has_nary_lexer_id<T> {};
}}}
#endif
@@ -0,0 +1,104 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// 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_META_COMPILER_APR_20_2009_0756PM)
#define BOOST_SPIRIT_LEX_META_COMPILER_APR_20_2009_0756PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/meta_compiler.hpp>
#include <boost/spirit/home/lex/domain.hpp>
#include <boost/spirit/home/lex/lexer_type.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
namespace boost { namespace spirit
{
template <typename T>
struct use_terminal<lex::domain, T
, typename enable_if<traits::is_lexer<T> >::type> // enables lexers
: mpl::true_ {};
namespace lex
{
template <typename T, typename Modifiers, typename Enable = void>
struct make_primitive // by default, return it as-is
{
typedef T result_type;
template <typename T_>
T_& operator()(T_& val, unused_type) const
{
return val;
}
template <typename T_>
T_ const& operator()(T_ const& val, unused_type) const
{
return val;
}
};
template <typename Tag, typename Elements
, typename Modifiers, typename Enable = void>
struct make_composite;
}
// Lex primitive meta-compiler
template <>
struct make_component<lex::domain, proto::tag::terminal>
{
template <typename Sig>
struct result;
template <typename This, typename Elements, typename Modifiers>
struct result<This(Elements, Modifiers)>
{
typedef typename lex::make_primitive<
typename remove_const<typename Elements::car_type>::type,
typename remove_reference<Modifiers>::type>::result_type
type;
};
template <typename Elements, typename Modifiers>
typename result<make_component(Elements, Modifiers)>::type
operator()(Elements const& elements, Modifiers const& modifiers) const
{
typedef typename remove_const<typename Elements::car_type>::type term;
return lex::make_primitive<term, Modifiers>()(elements.car, modifiers);
}
};
// Lex composite meta-compiler
template <typename Tag>
struct make_component<lex::domain, Tag>
{
template <typename Sig>
struct result;
template <typename This, typename Elements, typename Modifiers>
struct result<This(Elements, Modifiers)>
{
typedef typename
lex::make_composite<Tag, Elements
, typename remove_reference<Modifiers>::type>::result_type
type;
};
template <typename Elements, typename Modifiers>
typename result<make_component(Elements, Modifiers)>::type
operator()(Elements const& elements, Modifiers const& modifiers) const
{
return lex::make_composite<Tag, Elements, Modifiers>()(
elements, modifiers);
}
};
}}
#endif
@@ -0,0 +1,16 @@
// Copyright (c) 2001-2010 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_LEXER_PRIMITIVES_SEP_12_2009_0234PM)
#define BOOST_SPIRIT_LEXER_PRIMITIVES_SEP_12_2009_0234PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/lexer/char_token_def.hpp>
#include <boost/spirit/home/lex/lexer/string_token_def.hpp>
#endif
@@ -0,0 +1,20 @@
// 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_LEXER_QI_APR_21_2009_0205PM)
#define BOOST_SPIRIT_LEXER_QI_APR_21_2009_0205PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/qi/state_switcher.hpp>
#include <boost/spirit/home/lex/qi/in_state.hpp>
#include <boost/spirit/home/lex/qi/plain_token.hpp>
#include <boost/spirit/home/lex/qi/plain_tokenid.hpp>
#include <boost/spirit/home/lex/qi/plain_tokenid_mask.hpp>
#include <boost/spirit/home/lex/qi/plain_raw_token.hpp>
#endif
@@ -0,0 +1,32 @@
// 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_IN_STATE_OCT_09_2007_0748PM)
#define BOOST_SPIRIT_LEX_IN_STATE_OCT_09_2007_0748PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/proto/core.hpp>
///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace spirit { namespace qi
{
///////////////////////////////////////////////////////////////////////////
// The following is a helper template allowing to use the in_state()[] as
// a skip parser
///////////////////////////////////////////////////////////////////////////
template <typename Skipper, typename String = char const*>
struct in_state_skipper
: proto::subscript<
typename proto::terminal<
terminal_ex<tag::in_state, fusion::vector1<String> >
>::type
, Skipper
>::type {};
}}}
#endif
@@ -0,0 +1,149 @@
// 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_PLAIN_RAW_TOKEN_JUN_03_2011_0853PM)
#define BOOST_SPIRIT_LEX_PLAIN_RAW_TOKEN_JUN_03_2011_0853PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/qi/skip_over.hpp>
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/qi/meta_compiler.hpp>
#include <boost/spirit/home/qi/detail/assign_to.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/lexical_cast.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables raw_token
template <>
struct use_terminal<qi::domain, tag::raw_token>
: mpl::true_ {};
// enables raw_token(id)
template <typename A0>
struct use_terminal<qi::domain
, terminal_ex<tag::raw_token, fusion::vector1<A0> >
> : mpl::or_<is_integral<A0>, is_enum<A0> > {};
// enables *lazy* raw_token(id)
template <>
struct use_lazy_terminal<
qi::domain, tag::raw_token, 1
> : mpl::true_ {};
}}
namespace boost { namespace spirit { namespace qi
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::raw_token;
#endif
using spirit::raw_token_type;
///////////////////////////////////////////////////////////////////////////
template <typename TokenId>
struct plain_raw_token
: primitive_parser<plain_raw_token<TokenId> >
{
template <typename Context, typename Iterator>
struct attribute
{
typedef unused_type type;
};
plain_raw_token(TokenId const& id)
: id(id) {}
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) {
// simply match the token id with the id this component has
// been initialized with
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
token_type const& t = *first;
if (id_type(~0) == id_type(id) || id_type(id) == t.id()) {
spirit::traits::assign_to(t, attr);
++first;
return true;
}
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("raw_token",
"raw_token(" + boost::lexical_cast<utf8_string>(id) + ")");
}
TokenId id;
};
///////////////////////////////////////////////////////////////////////////
// Parser generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::raw_token, Modifiers>
{
typedef plain_raw_token<std::size_t> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type(std::size_t(~0));
}
};
template <typename Modifiers, typename TokenId>
struct make_primitive<terminal_ex<tag::raw_token, fusion::vector1<TokenId> >
, Modifiers>
{
typedef plain_raw_token<TokenId> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template<typename Idtype, typename Attr, typename Context, typename Iterator>
struct handles_container<qi::plain_raw_token<Idtype>, Attr, Context, Iterator>
: mpl::true_
{};
}}}
#endif
@@ -0,0 +1,242 @@
// 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_PLAIN_TOKEN_NOV_11_2007_0451PM)
#define BOOST_SPIRIT_LEX_PLAIN_TOKEN_NOV_11_2007_0451PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/qi/skip_over.hpp>
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/qi/meta_compiler.hpp>
#include <boost/spirit/home/qi/detail/assign_to.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/lexical_cast.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables token
template <>
struct use_terminal<qi::domain, tag::token>
: mpl::true_ {};
// enables token(id)
template <typename A0>
struct use_terminal<qi::domain
, terminal_ex<tag::token, fusion::vector1<A0> >
> : mpl::or_<is_integral<A0>, is_enum<A0> > {};
// enables token(idmin, idmax)
template <typename A0, typename A1>
struct use_terminal<qi::domain
, terminal_ex<tag::token, fusion::vector2<A0, A1> >
> : mpl::and_<
mpl::or_<is_integral<A0>, is_enum<A0> >
, mpl::or_<is_integral<A1>, is_enum<A1> >
> {};
// enables *lazy* token(id)
template <>
struct use_lazy_terminal<
qi::domain, tag::token, 1
> : mpl::true_ {};
// enables *lazy* token(idmin, idmax)
template <>
struct use_lazy_terminal<
qi::domain, tag::token, 2
> : mpl::true_ {};
}}
namespace boost { namespace spirit { namespace qi
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::token;
#endif
using spirit::token_type;
///////////////////////////////////////////////////////////////////////////
template <typename TokenId>
struct plain_token
: primitive_parser<plain_token<TokenId> >
{
template <typename Context, typename Iterator>
struct attribute
{
typedef typename Iterator::base_iterator_type iterator_type;
typedef iterator_range<iterator_type> type;
};
plain_token(TokenId const& id)
: id(id) {}
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) {
// simply match the token id with the id this component has
// been initialized with
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
token_type const& t = *first;
if (id_type(~0) == id_type(id) || id_type(id) == t.id()) {
spirit::traits::assign_to(t, attr);
++first;
return true;
}
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("token",
"token(" + boost::lexical_cast<utf8_string>(id) + ")");
}
TokenId id;
};
///////////////////////////////////////////////////////////////////////////
template <typename TokenId>
struct plain_token_range
: primitive_parser<plain_token_range<TokenId> >
{
template <typename Context, typename Iterator>
struct attribute
{
typedef typename Iterator::base_iterator_type iterator_type;
typedef iterator_range<iterator_type> type;
};
plain_token_range(TokenId const& idmin, TokenId const& idmax)
: idmin(idmin), idmax(idmax) {}
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) {
// simply match the token id with the id this component has
// been initialized with
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
token_type const& t = *first;
if (id_type(idmin) >= t.id() && id_type(idmin) <= t.id())
{
spirit::traits::assign_to(t, attr);
++first;
return true;
}
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("token_range"
, "token(" +
boost::lexical_cast<utf8_string>(idmin) + ", " +
boost::lexical_cast<utf8_string>(idmax) + ")"
);
return info("token_range");
}
TokenId idmin, idmax;
};
///////////////////////////////////////////////////////////////////////////
// Parser generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::token, Modifiers>
{
typedef plain_token<std::size_t> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type(std::size_t(~0));
}
};
template <typename Modifiers, typename TokenId>
struct make_primitive<terminal_ex<tag::token, fusion::vector1<TokenId> >
, Modifiers>
{
typedef plain_token<TokenId> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
template <typename Modifiers, typename TokenId>
struct make_primitive<terminal_ex<tag::token, fusion::vector2<TokenId, TokenId> >
, Modifiers>
{
typedef plain_token_range<TokenId> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args)
, fusion::at_c<1>(term.args));
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template<typename Idtype, typename Attr, typename Context, typename Iterator>
struct handles_container<qi::plain_token<Idtype>, Attr, Context, Iterator>
: mpl::true_
{};
template<typename Idtype, typename Attr, typename Context, typename Iterator>
struct handles_container<qi::plain_token_range<Idtype>, Attr, Context, Iterator>
: mpl::true_
{};
}}}
#endif
@@ -0,0 +1,242 @@
// 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_PLAIN_TOKENID_NOV_26_2010_0944AM)
#define BOOST_SPIRIT_LEX_PLAIN_TOKENID_NOV_26_2010_0944AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/qi/skip_over.hpp>
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/qi/meta_compiler.hpp>
#include <boost/spirit/home/qi/detail/assign_to.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/and.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/lexical_cast.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables tokenid
template <>
struct use_terminal<qi::domain, tag::tokenid>
: mpl::true_ {};
// enables tokenid(id)
template <typename A0>
struct use_terminal<qi::domain
, terminal_ex<tag::tokenid, fusion::vector1<A0> >
> : mpl::or_<is_integral<A0>, is_enum<A0> > {};
// enables tokenid(idmin, idmax)
template <typename A0, typename A1>
struct use_terminal<qi::domain
, terminal_ex<tag::tokenid, fusion::vector2<A0, A1> >
> : mpl::and_<
mpl::or_<is_integral<A0>, is_enum<A0> >
, mpl::or_<is_integral<A1>, is_enum<A1> >
> {};
// enables *lazy* tokenid(id)
template <>
struct use_lazy_terminal<
qi::domain, tag::tokenid, 1
> : mpl::true_ {};
// enables *lazy* tokenid(idmin, idmax)
template <>
struct use_lazy_terminal<
qi::domain, tag::tokenid, 2
> : mpl::true_ {};
}}
namespace boost { namespace spirit { namespace qi
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::tokenid;
#endif
using spirit::tokenid_type;
///////////////////////////////////////////////////////////////////////////
// The plain_tokenid represents a simple token defined by the lexer inside
// a Qi grammar. The difference to plain_token is that it exposes the
// matched token id instead of the iterator_range of the matched input.
template <typename TokenId>
struct plain_tokenid
: primitive_parser<plain_tokenid<TokenId> >
{
template <typename Context, typename Iterator>
struct attribute
{
typedef TokenId type;
};
plain_tokenid(TokenId const& id)
: id(id) {}
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) {
// simply match the token id with the id this component has
// been initialized with
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
token_type const& t = *first;
if (id_type(~0) == id_type(id) || id_type(id) == t.id()) {
spirit::traits::assign_to(id, attr);
++first;
return true;
}
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("tokenid",
"tokenid(" + boost::lexical_cast<utf8_string>(id) + ")");
}
TokenId id;
};
///////////////////////////////////////////////////////////////////////////
template <typename TokenId>
struct plain_tokenid_range
: primitive_parser<plain_tokenid_range<TokenId> >
{
template <typename Context, typename Iterator>
struct attribute
{
typedef TokenId type;
};
plain_tokenid_range(TokenId const& idmin, TokenId const& idmax)
: idmin(idmin), idmax(idmax) {}
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) {
// simply match the token id with the id this component has
// been initialized with
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
token_type const& t = *first;
if (id_type(idmin) >= t.id() && id_type(idmin) <= t.id())
{
spirit::traits::assign_to(t.id(), attr);
++first;
return true;
}
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("tokenid_range"
, "token(" +
boost::lexical_cast<utf8_string>(idmin) + ", " +
boost::lexical_cast<utf8_string>(idmax) + ")"
);
}
TokenId idmin, idmax;
};
///////////////////////////////////////////////////////////////////////////
// Parser generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers>
struct make_primitive<tag::tokenid, Modifiers>
{
typedef plain_tokenid<std::size_t> result_type;
result_type operator()(unused_type, unused_type) const
{
return result_type(std::size_t(~0));
}
};
template <typename Modifiers, typename TokenId>
struct make_primitive<terminal_ex<tag::tokenid, fusion::vector1<TokenId> >
, Modifiers>
{
typedef plain_tokenid<TokenId> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
template <typename Modifiers, typename TokenId>
struct make_primitive<terminal_ex<tag::tokenid, fusion::vector2<TokenId, TokenId> >
, Modifiers>
{
typedef plain_tokenid_range<TokenId> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args)
, fusion::at_c<1>(term.args));
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template<typename Idtype, typename Attr, typename Context, typename Iterator>
struct handles_container<qi::plain_tokenid<Idtype>, Attr, Context, Iterator>
: mpl::true_
{};
template<typename Idtype, typename Attr, typename Context, typename Iterator>
struct handles_container<qi::plain_tokenid_range<Idtype>, Attr, Context, Iterator>
: mpl::true_
{};
}}}
#endif
@@ -0,0 +1,138 @@
// 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_PLAIN_TOKENID_MASK_JUN_03_2011_0929PM)
#define BOOST_SPIRIT_LEX_PLAIN_TOKENID_MASK_JUN_03_2011_0929PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/qi/skip_over.hpp>
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/qi/meta_compiler.hpp>
#include <boost/spirit/home/qi/detail/assign_to.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/fusion/include/at.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/lexical_cast.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables tokenid_mask(id)
template <typename A0>
struct use_terminal<qi::domain
, terminal_ex<tag::tokenid_mask, fusion::vector1<A0> >
> : mpl::or_<is_integral<A0>, is_enum<A0> > {};
// enables *lazy* tokenid_mask(id)
template <>
struct use_lazy_terminal<
qi::domain, tag::tokenid_mask, 1
> : mpl::true_ {};
}}
namespace boost { namespace spirit { namespace qi
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::tokenid_mask;
#endif
using spirit::tokenid_mask_type;
///////////////////////////////////////////////////////////////////////////
// The plain_tokenid represents a simple token defined by the lexer inside
// a Qi grammar. The difference to plain_token is that it exposes the
// matched token id instead of the iterator_range of the matched input.
// Additionally it applies the given mask to the matched token id.
template <typename Mask>
struct plain_tokenid_mask
: primitive_parser<plain_tokenid_mask<Mask> >
{
template <typename Context, typename Iterator>
struct attribute
{
typedef Mask type;
};
plain_tokenid_mask(Mask const& mask)
: mask(mask) {}
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) {
// simply match the token id with the mask this component has
// been initialized with
typedef typename
boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
token_type const& t = *first;
if ((t.id() & mask) == id_type(mask))
{
spirit::traits::assign_to(t.id(), attr);
++first;
return true;
}
}
return false;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("tokenid_mask",
"tokenid_mask(" + boost::lexical_cast<utf8_string>(mask) + ")");
}
Mask mask;
};
///////////////////////////////////////////////////////////////////////////
// Parser generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers, typename Mask>
struct make_primitive<terminal_ex<tag::tokenid_mask, fusion::vector1<Mask> >
, Modifiers>
{
typedef plain_tokenid_mask<Mask> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(fusion::at_c<0>(term.args));
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template<typename Mask, typename Attr, typename Context, typename Iterator>
struct handles_container<qi::plain_tokenid_mask<Mask>, Attr, Context, Iterator>
: mpl::true_
{};
}}}
#endif
@@ -0,0 +1,270 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2010 Bryce Lelbach
//
// 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_STATE_SWITCHER_SEP_23_2007_0714PM)
#define BOOST_SPIRIT_LEX_STATE_SWITCHER_SEP_23_2007_0714PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/qi/detail/attributes.hpp>
#include <boost/spirit/home/support/common_terminals.hpp>
#include <boost/spirit/home/support/string_traits.hpp>
#include <boost/spirit/home/support/has_semantic_action.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/spirit/home/qi/skip_over.hpp>
#include <boost/spirit/home/qi/domain.hpp>
#include <boost/spirit/home/qi/parser.hpp>
#include <boost/spirit/home/qi/meta_compiler.hpp>
#include <boost/mpl/print.hpp>
namespace boost { namespace spirit
{
///////////////////////////////////////////////////////////////////////////
// Enablers
///////////////////////////////////////////////////////////////////////////
// enables set_state(s)
template <typename A0>
struct use_terminal<qi::domain
, terminal_ex<tag::set_state, fusion::vector1<A0> >
> : traits::is_string<A0> {};
// enables *lazy* set_state(s)
template <>
struct use_lazy_terminal<
qi::domain, tag::set_state, 1
> : mpl::true_ {};
// enables in_state(s)[p]
template <typename A0>
struct use_directive<qi::domain
, terminal_ex<tag::in_state, fusion::vector1<A0> >
> : traits::is_string<A0> {};
// enables *lazy* in_state(s)[p]
template <>
struct use_lazy_directive<
qi::domain, tag::in_state, 1
> : mpl::true_ {};
}}
namespace boost { namespace spirit { namespace qi
{
#ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
using spirit::set_state;
using spirit::in_state;
#endif
using spirit::set_state_type;
using spirit::in_state_type;
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Iterator>
inline std::size_t
set_lexer_state(Iterator& it, std::size_t state)
{
return it.set_state(state);
}
template <typename Iterator, typename Char>
inline std::size_t
set_lexer_state(Iterator& it, Char const* statename)
{
std::size_t state = it.map_state(statename);
// If the following assertion fires you probably used the
// set_state(...) or in_state(...)[...] lexer state switcher with
// a lexer state name unknown to the lexer (no token definitions
// have been associated with this lexer state).
BOOST_ASSERT(std::size_t(~0) != state);
return it.set_state(state);
}
}
///////////////////////////////////////////////////////////////////////////
// Parser switching the state of the underlying lexer component.
// This parser gets used for the set_state(...) construct.
///////////////////////////////////////////////////////////////////////////
template <typename State>
struct state_switcher
: primitive_parser<state_switcher<State> >
{
typedef typename
remove_const<typename traits::char_type_of<State>::type>::type
char_type;
typedef std::basic_string<char_type> string_type;
template <typename Context, typename Iterator>
struct attribute
{
typedef unused_type type;
};
state_switcher(char_type const* state)
: state(state) {}
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
// just switch the state and return success
detail::set_lexer_state(first, state.c_str());
return true;
}
template <typename Context>
info what(Context& /*context*/) const
{
return info("set_state");
}
string_type state;
};
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Iterator>
struct reset_state_on_exit
{
template <typename State>
reset_state_on_exit(Iterator& it_, State state_)
: it(it_)
, state(set_lexer_state(it_, traits::get_c_string(state_)))
{}
~reset_state_on_exit()
{
// reset the state of the underlying lexer instance
set_lexer_state(it, state);
}
Iterator& it;
std::size_t state;
private:
// silence MSVC warning C4512: assignment operator could not be generated
reset_state_on_exit& operator= (reset_state_on_exit const&);
};
}
///////////////////////////////////////////////////////////////////////////
// Parser, which switches the state of the underlying lexer component
// for the execution of the embedded sub-parser, switching the state back
// afterwards. This parser gets used for the in_state(...)[p] construct.
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename State>
struct state_switcher_context
: unary_parser<state_switcher_context<Subject, State> >
{
typedef Subject subject_type;
typedef typename traits::char_type_of<State>::type char_type;
typedef typename remove_const<char_type>::type non_const_char_type;
template <typename Context, typename Iterator>
struct attribute
{
typedef typename
traits::attribute_of<subject_type, Context, Iterator>::type
type;
};
state_switcher_context(Subject const& subject
, typename add_reference<State>::type state)
: subject(subject), state(state) {}
// The following conversion constructors are needed to make the
// in_state_switcher template usable
template <typename String>
state_switcher_context(
state_switcher_context<Subject, String> const& rhs)
: subject(rhs.subject), state(traits::get_c_string(rhs.state)) {}
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
// the state has to be reset at exit in any case
detail::reset_state_on_exit<Iterator> guard(first, state);
return subject.parse(first, last, context, skipper, attr);
}
template <typename Context>
info what(Context& context) const
{
return info("in_state", subject.what(context));
}
Subject subject;
State state;
private:
// silence MSVC warning C4512: assignment operator could not be generated
state_switcher_context& operator= (state_switcher_context const&);
};
///////////////////////////////////////////////////////////////////////////
// Parser generators: make_xxx function (objects)
///////////////////////////////////////////////////////////////////////////
template <typename Modifiers, typename State>
struct make_primitive<terminal_ex<tag::set_state, fusion::vector1<State> >
, Modifiers, typename enable_if<traits::is_string<State> >::type>
{
typedef typename add_const<State>::type const_string;
typedef state_switcher<const_string> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, unused_type) const
{
return result_type(traits::get_c_string(fusion::at_c<0>(term.args)));
}
};
template <typename State, typename Subject, typename Modifiers>
struct make_directive<terminal_ex<tag::in_state, fusion::vector1<State> >
, Subject, Modifiers>
{
typedef typename add_const<State>::type const_string;
typedef state_switcher_context<Subject, const_string> result_type;
template <typename Terminal>
result_type operator()(Terminal const& term, Subject const& subject
, unused_type) const
{
return result_type(subject, fusion::at_c<0>(term.args));
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename State>
struct has_semantic_action<qi::state_switcher_context<Subject, State> >
: unary_has_semantic_action<Subject> {};
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename State, typename Attribute
, typename Context, typename Iterator>
struct handles_container<qi::state_switcher_context<Subject, State>
, Attribute, Context, Iterator>
: unary_handles_container<Subject, Attribute, Context, Iterator> {};
}}}
#endif
@@ -0,0 +1,85 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
//
// 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_REFERENCE_APR_20_2009_0827AM)
#define BOOST_SPIRIT_LEX_REFERENCE_APR_20_2009_0827AM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/lex/meta_compiler.hpp>
#include <boost/spirit/home/lex/lexer_type.hpp>
#include <boost/spirit/home/qi/reference.hpp>
#include <boost/spirit/home/support/info.hpp>
#include <boost/spirit/home/support/handles_container.hpp>
#include <boost/ref.hpp>
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
// reference is a lexer that references another lexer (its Subject)
// all lexer components are at the same time
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename IdType = unused_type>
struct reference;
template <typename Subject>
struct reference<Subject, unused_type>
: qi::reference<Subject>
, lexer_type<reference<Subject> >
{
reference(Subject& subject)
: qi::reference<Subject>(subject) {}
template <typename LexerDef, typename String>
void collect(LexerDef& lexdef, String const& state
, String const& targetstate) const
{
this->ref.get().collect(lexdef, state, targetstate);
}
template <typename LexerDef>
void add_actions(LexerDef& lexdef) const
{
this->ref.get().add_actions(lexdef);
}
};
template <typename Subject, typename IdType>
struct reference : reference<Subject>
{
reference(Subject& subject)
: reference<Subject>(subject) {}
IdType id() const
{
return this->ref.get().id();
}
std::size_t unique_id() const
{
return this->ref.get().unique_id();
}
std::size_t state() const
{
return this->ref.get().state();
}
};
}}}
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
template <typename Subject, typename IdType
, typename Attribute, typename Context, typename Iterator>
struct handles_container<lex::reference<Subject, IdType>
, Attribute, Context, Iterator>
: handles_container<
typename remove_const<Subject>::type, Attribute, Context, Iterator>
{};
}}}
#endif
@@ -0,0 +1,325 @@
// 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_LEXER_PARSE_NOV_17_2007_0246PM)
#define BOOST_SPIRIT_LEXER_PARSE_NOV_17_2007_0246PM
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/spirit/home/qi/skip_over.hpp>
#include <boost/spirit/home/qi/parse.hpp>
#include <boost/spirit/home/qi/nonterminal/grammar.hpp>
#include <boost/spirit/home/support/unused.hpp>
#include <boost/spirit/home/lex/lexer.hpp>
#include <boost/mpl/assert.hpp>
namespace boost { namespace spirit { namespace lex
{
///////////////////////////////////////////////////////////////////////////
// Import skip_flag enumerator type from Qi namespace
using qi::skip_flag;
///////////////////////////////////////////////////////////////////////////
//
// The tokenize_and_parse() function is one of the main Spirit API
// functions. It simplifies using a lexer as the underlying token source
// while parsing a given input sequence.
//
// The function takes a pair of iterators spanning the underlying input
// stream to parse, the lexer object (built from the token definitions)
// and a parser object (built from the parser grammar definition).
//
// The second version of this function additionally takes an attribute to
// be used as the top level data structure instance the parser should use
// to store the recognized input to.
//
// The function returns true if the parsing succeeded (the given input
// sequence has been successfully matched by the given grammar).
//
// first, last: The pair of iterators spanning the underlying input
// sequence to parse. These iterators must at least
// conform to the requirements of the std::intput_iterator
// category.
// On exit the iterator 'first' will be updated to the
// position right after the last successfully matched
// token.
// lex: The lexer object (encoding the token definitions) to be
// used to convert the input sequence into a sequence of
// tokens. This token sequence is passed to the parsing
// process. The LexerExpr type must conform to the
// lexer interface described in the corresponding section
// of the documentation.
// xpr: The grammar object (encoding the parser grammar) to be
// used to match the token sequence generated by the lex
// object instance. The ParserExpr type must conform to
// the grammar interface described in the corresponding
// section of the documentation.
// attr: The top level attribute passed to the parser. It will
// be populated during the parsing of the input sequence.
// On exit it will hold the 'parser result' corresponding
// to the matched input sequence.
//
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Lexer, typename ParserExpr>
inline bool
tokenize_and_parse(Iterator& first, Iterator last, Lexer const& lex,
ParserExpr 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 qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
typename Lexer::iterator_type iter = lex.begin(first, last);
return compile<qi::domain>(xpr).parse(
iter, lex.end(), unused, unused, unused);
}
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Lexer, typename ParserExpr
, typename Attribute>
inline bool
tokenize_and_parse(Iterator& first, Iterator last, Lexer const& lex
, ParserExpr const& xpr, Attribute& attr)
{
// 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 qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
typename Lexer::iterator_type iter = lex.begin(first, last);
return compile<qi::domain>(xpr).parse(
iter, lex.end(), unused, unused, attr);
}
///////////////////////////////////////////////////////////////////////////
//
// The tokenize_and_phrase_parse() function is one of the main Spirit API
// functions. It simplifies using a lexer as the underlying token source
// while phrase parsing a given input sequence.
//
// The function takes a pair of iterators spanning the underlying input
// stream to parse, the lexer object (built from the token definitions)
// and a parser object (built from the parser grammar definition). The
// additional skipper parameter will be used as the skip parser during
// the parsing process.
//
// The second version of this function additionally takes an attribute to
// be used as the top level data structure instance the parser should use
// to store the recognized input to.
//
// The function returns true if the parsing succeeded (the given input
// sequence has been successfully matched by the given grammar).
//
// first, last: The pair of iterators spanning the underlying input
// sequence to parse. These iterators must at least
// conform to the requirements of the std::intput_iterator
// category.
// On exit the iterator 'first' will be updated to the
// position right after the last successfully matched
// token.
// lex: The lexer object (encoding the token definitions) to be
// used to convert the input sequence into a sequence of
// tokens. This token sequence is passed to the parsing
// process. The LexerExpr type must conform to the
// lexer interface described in the corresponding section
// of the documentation.
// xpr: The grammar object (encoding the parser grammar) to be
// used to match the token sequence generated by the lex
// object instance. The ParserExpr type must conform to
// the grammar interface described in the corresponding
// section of the documentation.
// skipper: The skip parser to be used while parsing the given
// input sequence. Note, the skip parser will have to
// act on the same token sequence as the main parser
// 'xpr'.
// post_skip: The post_skip flag controls whether the function will
// invoke an additional post skip after the main parser
// returned.
// attr: The top level attribute passed to the parser. It will
// be populated during the parsing of the input sequence.
// On exit it will hold the 'parser result' corresponding
// to the matched input sequence.
//
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Lexer, typename ParserExpr
, typename Skipper>
inline bool
tokenize_and_phrase_parse(Iterator& first, Iterator last
, Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
, BOOST_SCOPED_ENUM(skip_flag) post_skip = skip_flag::postskip)
{
// 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 qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
typedef
typename spirit::result_of::compile<qi::domain, Skipper>::type
skipper_type;
skipper_type const skipper_ = compile<qi::domain>(skipper);
typename Lexer::iterator_type iter = lex.begin(first, last);
typename Lexer::iterator_type end = lex.end();
if (!compile<qi::domain>(xpr).parse(
iter, end, unused, skipper_, unused))
return false;
// do a final post-skip
if (post_skip == skip_flag::postskip)
qi::skip_over(iter, end, skipper_);
return true;
}
template <typename Iterator, typename Lexer, typename ParserExpr
, typename Skipper, typename Attribute>
inline bool
tokenize_and_phrase_parse(Iterator& first, Iterator last
, Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
, BOOST_SCOPED_ENUM(skip_flag) post_skip, Attribute& attr)
{
// 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 qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
typedef
typename spirit::result_of::compile<qi::domain, Skipper>::type
skipper_type;
skipper_type const skipper_ = compile<qi::domain>(skipper);
typename Lexer::iterator_type iter = lex.begin(first, last);
typename Lexer::iterator_type end = lex.end();
if (!compile<qi::domain>(xpr).parse(
iter, end, unused, skipper_, attr))
return false;
// do a final post-skip
if (post_skip == skip_flag::postskip)
qi::skip_over(iter, end, skipper_);
return true;
}
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Lexer, typename ParserExpr
, typename Skipper, typename Attribute>
inline bool
tokenize_and_phrase_parse(Iterator& first, Iterator last
, Lexer const& lex, ParserExpr const& xpr, Skipper const& skipper
, Attribute& attr)
{
return tokenize_and_phrase_parse(first, last, lex, xpr, skipper
, skip_flag::postskip, attr);
}
///////////////////////////////////////////////////////////////////////////
//
// The tokenize() function is one of the main Spirit API functions. It
// simplifies using a lexer to tokenize a given input sequence. It's main
// purpose is to use the lexer to tokenize all the input.
//
// The second version below discards all generated tokens afterwards.
// This is useful whenever all the needed functionality has been
// implemented directly inside the lexer semantic actions, which are being
// executed while the tokens are matched.
//
// The function takes a pair of iterators spanning the underlying input
// stream to scan, the lexer object (built from the token definitions),
// and a (optional) functor being called for each of the generated tokens.
//
// The function returns true if the scanning of the input succeeded (the
// given input sequence has been successfully matched by the given token
// definitions).
//
// first, last: The pair of iterators spanning the underlying input
// sequence to parse. These iterators must at least
// conform to the requirements of the std::intput_iterator
// category.
// On exit the iterator 'first' will be updated to the
// position right after the last successfully matched
// token.
// lex: The lexer object (encoding the token definitions) to be
// used to convert the input sequence into a sequence of
// tokens. The LexerExpr type must conform to the
// lexer interface described in the corresponding section
// of the documentation.
// f: A functor (callable object) taking a single argument of
// the token type and returning a bool, indicating whether
// the tokenization should be canceled.
// initial_state: The name of the state the lexer should start matching.
// The default value is zero, causing the lexer to start
// in its 'INITIAL' state.
//
///////////////////////////////////////////////////////////////////////////
namespace detail
{
template <typename Token, typename F>
bool tokenize_callback(Token const& t, F f)
{
return f(t);
}
template <typename Token, typename Eval>
bool tokenize_callback(Token const& t, phoenix::actor<Eval> const& f)
{
f(t);
return true;
}
template <typename Token>
bool tokenize_callback(Token const& t, void (*f)(Token const&))
{
f(t);
return true;
}
template <typename Token>
bool tokenize_callback(Token const& t, bool (*f)(Token const&))
{
return f(t);
}
}
template <typename Iterator, typename Lexer, typename F>
inline bool
tokenize(Iterator& first, Iterator last, Lexer const& lex, F f
, typename Lexer::char_type const* initial_state = 0)
{
typedef typename Lexer::iterator_type iterator_type;
iterator_type iter = lex.begin(first, last, initial_state);
iterator_type end = lex.end();
for (/**/; iter != end && token_is_valid(*iter); ++iter)
{
if (!detail::tokenize_callback(*iter, f))
return false;
}
return (iter == end) ? true : false;
}
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Lexer>
inline bool
tokenize(Iterator& first, Iterator last, Lexer const& lex
, typename Lexer::char_type const* initial_state = 0)
{
typedef typename Lexer::iterator_type iterator_type;
iterator_type iter = lex.begin(first, last, initial_state);
iterator_type end = lex.end();
while (iter != end && token_is_valid(*iter))
++iter;
return (iter == end) ? true : false;
}
}}}
#endif
@@ -0,0 +1,114 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
// Copyright (c) 2001-2011 Joel de Guzman
// Copyright (c) 2009 Carl Barron
//
// 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_PP_IS_ITERATING)
#if !defined(BOOST_SPIRIT_LEXER_PARSE_ATTR_MAY_27_2009_0926AM)
#define BOOST_SPIRIT_LEXER_PARSE_ATTR_MAY_27_2009_0926AM
#include <boost/spirit/home/lex/tokenize_and_parse.hpp>
#include <boost/fusion/include/vector.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#define BOOST_PP_FILENAME_1 <boost/spirit/home/lex/tokenize_and_parse_attr.hpp>
#define BOOST_PP_ITERATION_LIMITS (2, SPIRIT_ARGUMENTS_LIMIT)
#include BOOST_PP_ITERATE()
#endif
///////////////////////////////////////////////////////////////////////////////
//
// Preprocessor vertical repetition code
//
///////////////////////////////////////////////////////////////////////////////
#else // defined(BOOST_PP_IS_ITERATING)
#define N BOOST_PP_ITERATION()
#define BOOST_SPIRIT_QI_ATTRIBUTE_REFERENCE(z, n, A) BOOST_PP_CAT(A, n)&
namespace boost { namespace spirit { namespace lex
{
template <typename Iterator, typename Lexer, typename ParserExpr
, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
tokenize_and_parse(Iterator& first, Iterator last, Lexer const& lex
, ParserExpr const& expr, BOOST_PP_ENUM_BINARY_PARAMS(N, A, & attr))
{
// 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 qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
typedef fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_QI_ATTRIBUTE_REFERENCE, A)
> vector_type;
vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
typename Lexer::iterator_type iter = lex.begin(first, last);
return compile<qi::domain>(expr).parse(
iter, lex.end(), unused, unused, attr);
}
///////////////////////////////////////////////////////////////////////////
template <typename Iterator, typename Lexer, typename ParserExpr
, typename Skipper, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
tokenize_and_phrase_parse(Iterator& first, Iterator last, Lexer const& lex
, ParserExpr const& expr, Skipper const& skipper
, BOOST_SCOPED_ENUM(skip_flag) post_skip
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, & attr))
{
// Report invalid expression error as early as possible.
// If you got an error_invalid_expression error message here,
// then either the expression (expr) or skipper is not a valid
// spirit qi expression.
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, ParserExpr);
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Skipper);
typedef
typename spirit::result_of::compile<qi::domain, Skipper>::type
skipper_type;
skipper_type const skipper_ = compile<qi::domain>(skipper);
typedef fusion::vector<
BOOST_PP_ENUM(N, BOOST_SPIRIT_QI_ATTRIBUTE_REFERENCE, A)
> vector_type;
vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
typename Lexer::iterator_type iter = lex.begin(first, last);
if (!compile<qi::domain>(expr).parse(
iter, lex.end(), unused, skipper_, attr))
return false;
if (post_skip == skip_flag::postskip)
qi::skip_over(first, last, skipper_);
return true;
}
template <typename Iterator, typename Lexer, typename ParserExpr
, typename Skipper, BOOST_PP_ENUM_PARAMS(N, typename A)>
inline bool
tokenize_and_phrase_parse(Iterator& first, Iterator last, Lexer const& lex
, ParserExpr const& expr, Skipper const& skipper
, BOOST_PP_ENUM_BINARY_PARAMS(N, A, & attr))
{
return tokenize_and_phrase_parse(first, last, expr, skipper
, skip_flag::postskip, BOOST_PP_ENUM_PARAMS(N, attr));
}
}}}
#undef BOOST_SPIRIT_QI_ATTRIBUTE_REFERENCE
#undef N
#endif