|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r76248 - in trunk: boost/spirit/home/karma/detail boost/spirit/home/karma/nonterminal boost/spirit/home/karma/operator boost/spirit/home/lex/qi libs/spirit/doc
From: hartmut.kaiser_at_[hidden]
Date: 2011-12-31 14:39:44
Author: hkaiser
Date: 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
New Revision: 76248
URL: http://svn.boost.org/trac/boost/changeset/76248
Log:
Spirit: improving error reporting from lexer tokens
Text files modified:
trunk/boost/spirit/home/karma/detail/extract_from.hpp | 34 ++++++------
trunk/boost/spirit/home/karma/detail/pass_container.hpp | 56 ++++++++++----------
trunk/boost/spirit/home/karma/nonterminal/rule.hpp | 2
trunk/boost/spirit/home/karma/operator/sequence.hpp | 38 ++++++------
trunk/boost/spirit/home/lex/qi/plain_raw_token.hpp | 16 +++--
trunk/boost/spirit/home/lex/qi/plain_token.hpp | 107 +++++++++++++++++++++++++++++++++++--
trunk/boost/spirit/home/lex/qi/plain_tokenid.hpp | 112 ++++++++++++++++++++++++++++++++++++---
trunk/boost/spirit/home/lex/qi/plain_tokenid_mask.hpp | 20 +++---
trunk/libs/spirit/doc/what_s_new.qbk | 5 +
9 files changed, 292 insertions(+), 98 deletions(-)
Modified: trunk/boost/spirit/home/karma/detail/extract_from.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/extract_from.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/extract_from.hpp 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -23,8 +23,8 @@
namespace boost { namespace spirit { namespace traits
{
///////////////////////////////////////////////////////////////////////////
- // This file contains attribute extraction utilities. The utilities
- // provided also accept spirit's unused_type; all no-ops. Compiler
+ // This file contains attribute extraction utilities. The utilities
+ // provided also accept spirit's unused_type; all no-ops. Compiler
// optimization will easily strip these away.
///////////////////////////////////////////////////////////////////////////
@@ -33,13 +33,13 @@
///////////////////////////////////////////////////////////////////////
// extract first and second element of a fusion sequence
template <typename T>
- struct add_const_ref
- : add_reference<typename add_const<T>::type>
+ struct add_const_ref
+ : add_reference<typename add_const<T>::type>
{};
template <typename T, int N>
- struct value_at_c
- : add_const_ref<typename fusion::result_of::value_at_c<T, N>::type>
+ struct value_at_c
+ : add_const_ref<typename fusion::result_of::value_at_c<T, N>::type>
{};
}
@@ -47,7 +47,7 @@
template <typename Attribute, typename Exposed, typename Enable/*= void*/>
struct extract_from_attribute
{
- typedef typename traits::one_element_sequence<Attribute>::type
+ typedef typename traits::one_element_sequence<Attribute>::type
is_one_element_sequence;
typedef typename mpl::eval_if<
@@ -63,7 +63,7 @@
}
// This handles the case where the attribute is a single element fusion
- // sequence. We silently extract the only element and treat it as the
+ // sequence. We silently extract the only element and treat it as the
// attribute to generate output from.
template <typename Context>
static type call(Attribute const& attr, Context& ctx, mpl::true_)
@@ -78,7 +78,7 @@
}
};
- // This handles optional attributes.
+ // This handles optional attributes.
template <typename Attribute, typename Exposed>
struct extract_from_attribute<boost::optional<Attribute>, Exposed>
{
@@ -103,7 +103,7 @@
}
};
- // This handles attributes wrapped inside a boost::ref().
+ // This handles attributes wrapped inside a boost::ref().
template <typename Attribute, typename Exposed>
struct extract_from_attribute<reference_wrapper<Attribute>, Exposed>
{
@@ -120,14 +120,14 @@
template <typename Attribute, typename Exposed, typename Enable>
struct extract_from_container
{
- typedef typename traits::container_value<Attribute const>::type
+ typedef typename traits::container_value<Attribute const>::type
value_type;
- typedef typename is_convertible<value_type, Exposed>::type
+ typedef typename is_convertible<value_type, Exposed>::type
is_convertible_to_value_type;
typedef typename mpl::if_<
mpl::or_<
- is_same<value_type, Exposed>, is_same<Attribute, Exposed> >
+ is_same<value_type, Exposed>, is_same<Attribute, Exposed> >
, Exposed const&, Exposed
>::type type;
@@ -137,7 +137,7 @@
static type call(Attribute const& attr, Context&, mpl::true_, Pred)
{
// return first element from container
- typedef typename traits::container_iterator<Attribute const>::type
+ typedef typename traits::container_iterator<Attribute const>::type
iterator_type;
iterator_type it = traits::begin(attr);
@@ -176,7 +176,7 @@
static type call(Attribute const& attr, Context& ctx)
{
typedef typename mpl::and_<
- traits::is_string<Exposed>, traits::is_string<Attribute>
+ traits::is_string<Exposed>, traits::is_string<Attribute>
>::type handle_strings;
// return first element from container
@@ -208,7 +208,7 @@
return extract_from_attribute<Attribute, Exposed>::call(attr, ctx);
}
- // overload for containers (but not for variants or optionals
+ // overload for containers (but not for variants or optionals
// holding containers)
template <typename Exposed, typename Attribute, typename Context>
inline typename spirit::result_of::extract_from<Exposed, Attribute>::type
@@ -230,7 +230,7 @@
typedef typename mpl::and_<
traits::is_container<Attribute>
, traits::not_is_variant<Attribute>
- , traits::not_is_optional<Attribute>
+ , traits::not_is_optional<Attribute>
>::type is_not_wrapped_container;
return detail::extract_from<Exposed>(attr, ctx
Modified: trunk/boost/spirit/home/karma/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/pass_container.hpp (original)
+++ trunk/boost/spirit/home/karma/detail/pass_container.hpp 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -38,17 +38,17 @@
Sequence
, typename traits::is_weak_substitute<Attribute, ValueType>::type
, typename mpl::not_<
- traits::is_weak_substitute<Attribute, ValueType>
+ traits::is_weak_substitute<Attribute, ValueType>
>::type>
{};
- // pass_through_container: utility to check decide whether a provided
- // container attribute needs to be passed through to the current component
+ // pass_through_container: utility to check decide whether a provided
+ // container attribute needs to be passed through to the current component
// or of we need to split the container by passing along instances of its
// value type
- // if the expected attribute of the current component is neither a Fusion
- // sequence nor a container, we will pass through the provided container
+ // if the expected attribute of the current component is neither a Fusion
+ // sequence nor a container, we will pass through the provided container
// only if its value type is not compatible with the component
template <typename Container, typename ValueType, typename Attribute
, typename Sequence, typename Enable = void>
@@ -58,9 +58,9 @@
// Specialization for fusion sequences, in this case we check whether all
// the types in the sequence are convertible to the lhs attribute.
- //
+ //
// We return false if the rhs attribute itself is a fusion sequence, which
- // is compatible with the LHS sequence (we want to pass through this
+ // is compatible with the LHS sequence (we want to pass through this
// attribute without it being split apart).
template <typename Container, typename ValueType, typename Attribute
, typename Sequence = mpl::true_>
@@ -71,7 +71,7 @@
{};
// If the value type of the container is not a Fusion sequence, we pass
- // through the container if each of the elements of the Attribute
+ // through the container if each of the elements of the Attribute
// sequence is compatible with either the container or its value type.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence
@@ -87,7 +87,7 @@
};
// If both, the Attribute and the value type of the provided container
- // are Fusion sequences, we pass the container only if the two
+ // are Fusion sequences, we pass the container only if the two
// sequences are not compatible.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
@@ -115,14 +115,14 @@
// Specialization for containers
//
// If the value type of the attribute of the current component is not
- // a Fusion sequence, we have to pass through the provided container if
+ // a Fusion sequence, we have to pass through the provided container if
// both are compatible.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence, typename AttributeValueType
, bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
struct pass_through_container_container
: mpl::or_<
- traits::is_weak_substitute<Container, Attribute>
+ traits::is_weak_substitute<Container, Attribute>
, traits::is_weak_substitute<Container, AttributeValueType> >
{};
@@ -148,16 +148,16 @@
// Specialization for exposed optional attributes
//
- // If the type embedded in the exposed optional is not a Fusion
+ // If the type embedded in the exposed optional is not a Fusion
// sequence we pass through the container attribute if it is compatible
- // either to the optionals embedded type or to the containers value
+ // either to the optionals embedded type or to the containers value
// type.
template <typename Container, typename ValueType, typename Attribute
, typename Sequence
, bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
struct pass_through_container_optional
: mpl::or_<
- traits::is_weak_substitute<Container, Attribute>
+ traits::is_weak_substitute<Container, Attribute>
, traits::is_weak_substitute<ValueType, Attribute> >
{};
@@ -175,7 +175,7 @@
template <typename Container, typename ValueType, typename Attribute
, typename Sequence>
struct pass_through_container
- : pass_through_container_base<Container, ValueType, Attribute, Sequence>
+ : pass_through_container_base<Container, ValueType, Attribute, Sequence>
{};
// Handle optional attributes
@@ -184,7 +184,7 @@
struct pass_through_container<
Container, ValueType, boost::optional<Attribute>, Sequence>
: pass_through_container_optional<
- Container, ValueType, Attribute, Sequence>
+ Container, ValueType, Attribute, Sequence>
{};
// If both, the containers value type and the exposed attribute type are
@@ -199,8 +199,8 @@
{};
// Specialization for exposed variant attributes
- //
- // We pass through the container attribute if at least one of the embedded
+ //
+ // We pass through the container attribute if at least one of the embedded
// types in the variant requires to pass through the attribute
#define BOOST_SPIRIT_PASS_THROUGH_CONTAINER(z, N, _) \
@@ -252,7 +252,7 @@
typedef typename F::context_type context_type;
pass_container(F const& f, Iterator begin, Iterator end)
- : f(f), iter(begin), end(end)
+ : f(f), iter(begin), end(end)
{}
bool is_at_end() const
@@ -271,7 +271,7 @@
bool dispatch_container(Component const& component, mpl::false_) const
{
// get the next value to generate from container
- if (!is_at_end() && !f(component, traits::deref(iter)))
+ if (!is_at_end() && !f(component, traits::deref(iter)))
{
// needs to return false as long as everything is ok
traits::next(iter);
@@ -282,8 +282,8 @@
return true;
}
- // this is for the case when the current element is able to handle an
- // attribute which is a container itself, this element will push its
+ // this is for the case when the current element is able to handle an
+ // attribute which is a container itself, this element will push its
// data directly into the attribute container
template <typename Component>
bool dispatch_container(Component const& component, mpl::true_) const
@@ -292,7 +292,7 @@
}
///////////////////////////////////////////////////////////////////////
- // this is for the case when the current element doesn't expect an
+ // this is for the case when the current element doesn't expect an
// attribute
template <typename Component>
bool dispatch_attribute(Component const& component, mpl::false_) const
@@ -305,15 +305,15 @@
bool dispatch_attribute(Component const& component, mpl::true_) const
{
typedef typename traits::container_value<Attr>::type value_type;
- typedef typename
+ typedef typename
traits::attribute_of<Component, context_type>::type
lhs_attribute;
// this predicate detects, whether the value type of the container
- // attribute is a substitute for the attribute of the current
- // element
+ // attribute is a substitute for the attribute of the current
+ // element
typedef mpl::and_<
- traits::handles_container<Component, Attr, context_type>
+ traits::handles_container<Component, Attr, context_type>
, traits::pass_through_container<
Attr, value_type, lhs_attribute, Sequence, karma::domain>
> predicate;
@@ -328,7 +328,7 @@
{
// we need to dispatch depending on the type of the attribute
// of the current element (component). If this is has no attribute
- // we shouldn't use an element of the container but unused_type
+ // we shouldn't use an element of the container but unused_type
// instead
typedef traits::not_is_unused<
typename traits::attribute_of<Component, context_type>::type
Modified: trunk/boost/spirit/home/karma/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/rule.hpp (original)
+++ trunk/boost/spirit/home/karma/nonterminal/rule.hpp 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -436,7 +436,7 @@
typename attribute_of<
karma::rule<IteratorA, T1, T2, T3, T4>
, Context, IteratorB
- >::type, Attribute>
+ >::type, Attribute>
{};
}}}
Modified: trunk/boost/spirit/home/karma/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/sequence.hpp (original)
+++ trunk/boost/spirit/home/karma/operator/sequence.hpp 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -138,14 +138,14 @@
OutputIterator, Context, Delimiter> fail_function;
typedef traits::attribute_not_unused<Context> predicate;
- // wrap the attribute in a tuple if it is not a tuple or if the
+ // wrap the attribute in a tuple if it is not a tuple or if the
// attribute of this sequence is a single element tuple
typedef typename attribute<Context>::type_ attr_type_;
typename traits::wrap_if_not_tuple<Attribute
, typename mpl::and_<
traits::one_element_sequence<attr_type_>
, mpl::not_<traits::one_element_sequence<Attribute> >
- >::type
+ >::type
>::type attr(attr_);
// return false if *any* of the generators fail
@@ -155,12 +155,12 @@
typedef typename traits::attribute_size<Attribute>::type size_type;
// fail generating if sequences have not the same (logical) length
- return !r && (!Strict::value ||
- // This ignores container element count (which is not good),
- // but allows valid attributes to succeed. This will lead to
+ return !r && (!Strict::value ||
+ // This ignores container element count (which is not good),
+ // but allows valid attributes to succeed. This will lead to
// false positives (failing generators, even if they shouldn't)
- // if the embedded component is restricting the number of
- // container elements it consumes (i.e. repeat). This solution
+ // if the embedded component is restricting the number of
+ // container elements it consumes (i.e. repeat). This solution
// is not optimal but much better than letting _all_ repetitive
// components fail.
Pred1::value ||
@@ -184,17 +184,17 @@
typename add_const<Attribute>::type
>::type iterator_type;
- typedef
- typename traits::make_indirect_iterator<iterator_type>::type
+ typedef
+ typename traits::make_indirect_iterator<iterator_type>::type
indirect_iterator_type;
typedef detail::pass_container<
- fail_function, Attribute, indirect_iterator_type, mpl::true_>
+ fail_function, Attribute, indirect_iterator_type, mpl::true_>
pass_container;
iterator_type begin = traits::begin(attr_);
iterator_type end = traits::end(attr_);
- pass_container pass(fail_function(sink, ctx, d),
+ pass_container pass(fail_function(sink, ctx, d),
indirect_iterator_type(begin), indirect_iterator_type(end));
bool r = fusion::any(elements, pass);
@@ -210,11 +210,11 @@
bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d
, Attribute const& attr) const
{
- typedef typename traits::is_container<Attribute>::type
+ typedef typename traits::is_container<Attribute>::type
is_container;
typedef typename attribute<Context>::type_ attr_type_;
- typedef typename traits::one_element_sequence<attr_type_>::type
+ typedef typename traits::one_element_sequence<attr_type_>::type
is_one_element_sequence;
return generate_impl(sink, ctx, d, attr, is_container()
@@ -234,7 +234,7 @@
};
template <typename Elements>
- struct sequence
+ struct sequence
: base_sequence<Elements, mpl::false_, sequence<Elements> >
{
typedef base_sequence<Elements, mpl::false_, sequence> base_sequence_;
@@ -244,10 +244,10 @@
};
template <typename Elements>
- struct strict_sequence
+ struct strict_sequence
: base_sequence<Elements, mpl::true_, strict_sequence<Elements> >
{
- typedef base_sequence<Elements, mpl::true_, strict_sequence>
+ typedef base_sequence<Elements, mpl::true_, strict_sequence>
base_sequence_;
strict_sequence(Elements const& subject)
@@ -260,12 +260,12 @@
namespace detail
{
template <typename Elements, bool strict_mode = false>
- struct make_sequence
+ struct make_sequence
: make_nary_composite<Elements, sequence>
{};
template <typename Elements>
- struct make_sequence<Elements, true>
+ struct make_sequence<Elements, true>
: make_nary_composite<Elements, strict_sequence>
{};
}
@@ -283,7 +283,7 @@
{
typedef iterator_range<detail::indirect_iterator<Iterator> > type;
};
-}}}
+}}}
namespace boost { namespace spirit { namespace traits
{
Modified: trunk/boost/spirit/home/lex/qi/plain_raw_token.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/qi/plain_raw_token.hpp (original)
+++ trunk/boost/spirit/home/lex/qi/plain_raw_token.hpp 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -1,6 +1,6 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
+//
+// 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)
@@ -25,6 +25,7 @@
#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
{
@@ -59,7 +60,7 @@
///////////////////////////////////////////////////////////////////////////
template <typename TokenId>
- struct plain_raw_token
+ struct plain_raw_token
: primitive_parser<plain_raw_token<TokenId> >
{
template <typename Context, typename Iterator>
@@ -80,11 +81,11 @@
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
+ // simply match the token id with the id this component has
// been initialized with
- typedef typename
- boost::detail::iterator_traits<Iterator>::value_type
+ typedef typename
+ boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
@@ -101,7 +102,8 @@
template <typename Context>
info what(Context& /*context*/) const
{
- return info("token");
+ return info("raw_token",
+ "raw_token(" + boost::lexical_cast<utf8_string>(id) + ")");
}
TokenId id;
Modified: trunk/boost/spirit/home/lex/qi/plain_token.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/qi/plain_token.hpp (original)
+++ trunk/boost/spirit/home/lex/qi/plain_token.hpp 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -1,6 +1,6 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
+//
+// 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)
@@ -23,8 +23,10 @@
#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
{
@@ -43,12 +45,26 @@
, 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
@@ -60,7 +76,7 @@
///////////////////////////////////////////////////////////////////////////
template <typename TokenId>
- struct plain_token
+ struct plain_token
: primitive_parser<plain_token<TokenId> >
{
template <typename Context, typename Iterator>
@@ -82,11 +98,11 @@
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
+ // simply match the token id with the id this component has
// been initialized with
- typedef typename
- boost::detail::iterator_traits<Iterator>::value_type
+ typedef typename
+ boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
@@ -103,13 +119,71 @@
template <typename Context>
info what(Context& /*context*/) const
{
- return info("token");
+ 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>
@@ -135,6 +209,20 @@
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
@@ -144,6 +232,11 @@
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
Modified: trunk/boost/spirit/home/lex/qi/plain_tokenid.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/qi/plain_tokenid.hpp (original)
+++ trunk/boost/spirit/home/lex/qi/plain_tokenid.hpp 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -1,6 +1,6 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
+//
+// 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)
@@ -23,8 +23,10 @@
#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
{
@@ -43,11 +45,26 @@
, 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
@@ -58,11 +75,11 @@
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
+ // 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
+ struct plain_tokenid
: primitive_parser<plain_tokenid<TokenId> >
{
template <typename Context, typename Iterator>
@@ -83,11 +100,11 @@
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
+ // simply match the token id with the id this component has
// been initialized with
- typedef typename
- boost::detail::iterator_traits<Iterator>::value_type
+ typedef typename
+ boost::detail::iterator_traits<Iterator>::value_type
token_type;
typedef typename token_type::id_type id_type;
@@ -104,17 +121,73 @@
template <typename Context>
info what(Context& /*context*/) const
{
- return info("tokenid");
+ 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(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>
+ struct make_primitive<tag::tokenid, Modifiers>
{
typedef plain_tokenid<std::size_t> result_type;
@@ -136,6 +209,20 @@
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
@@ -145,6 +232,11 @@
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
Modified: trunk/boost/spirit/home/lex/qi/plain_tokenid_mask.hpp
==============================================================================
--- trunk/boost/spirit/home/lex/qi/plain_tokenid_mask.hpp (original)
+++ trunk/boost/spirit/home/lex/qi/plain_tokenid_mask.hpp 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -1,6 +1,6 @@
// Copyright (c) 2001-2011 Hartmut Kaiser
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
+//
+// 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)
@@ -25,6 +25,7 @@
#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
{
@@ -53,8 +54,8 @@
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
+ // 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>
@@ -79,16 +80,16 @@
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
+ // simply match the token id with the mask this component has
// been initialized with
- typedef typename
- boost::detail::iterator_traits<Iterator>::value_type
+ 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))
+ if ((t.id() & mask) == id_type(mask))
{
spirit::traits::assign_to(t.id(), attr);
++first;
@@ -101,7 +102,8 @@
template <typename Context>
info what(Context& /*context*/) const
{
- return info("tokenid_mask");
+ return info("tokenid_mask",
+ "tokenid_mask(" + boost::lexical_cast<utf8_string>(mask) + ")");
}
Mask mask;
Modified: trunk/libs/spirit/doc/what_s_new.qbk
==============================================================================
--- trunk/libs/spirit/doc/what_s_new.qbk (original)
+++ trunk/libs/spirit/doc/what_s_new.qbk 2011-12-31 14:39:42 EST (Sat, 31 Dec 2011)
@@ -15,6 +15,11 @@
* Integrated Vitaly Budovski's patch to add binary floating point parsers and
generators.
+* Fixed #6253: `lex::lexertl::generate_static_dfa` compiler errors if lexer has
+ wchar_t as underlying stream type.
+* Added the possibility to match a token range when parsing with a lexer by
+ using `qi::token(min, max)`, or `qi::tokenid(min, max)`. Both parsers match
+ any token with a token id in the range [min, max].
[endsect]
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk