summaryrefslogtreecommitdiff
path: root/boost/wave/grammars/cpp_expression_grammar.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/wave/grammars/cpp_expression_grammar.hpp')
-rw-r--r--boost/wave/grammars/cpp_expression_grammar.hpp870
1 files changed, 870 insertions, 0 deletions
diff --git a/boost/wave/grammars/cpp_expression_grammar.hpp b/boost/wave/grammars/cpp_expression_grammar.hpp
new file mode 100644
index 0000000000..a52d36a5c8
--- /dev/null
+++ b/boost/wave/grammars/cpp_expression_grammar.hpp
@@ -0,0 +1,870 @@
+/*=============================================================================
+ Boost.Wave: A Standard compliant C++ preprocessor library
+
+ http://www.boost.org/
+
+ 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(CPP_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED)
+#define CPP_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED
+
+#include <boost/wave/wave_config.hpp>
+
+#include <boost/assert.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_closure.hpp>
+#include <boost/spirit/include/classic_if.hpp>
+#include <boost/spirit/include/classic_assign_actor.hpp>
+#include <boost/spirit/include/classic_push_back_actor.hpp>
+
+#include <boost/spirit/include/phoenix1_functions.hpp>
+#include <boost/spirit/include/phoenix1_operators.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+#include <boost/spirit/include/phoenix1_statements.hpp>
+#include <boost/spirit/include/phoenix1_casts.hpp>
+
+#include <boost/wave/token_ids.hpp>
+
+#include <boost/wave/cpp_exceptions.hpp>
+#include <boost/wave/grammars/cpp_expression_grammar_gen.hpp>
+#include <boost/wave/grammars/cpp_literal_grammar_gen.hpp>
+#include <boost/wave/grammars/cpp_expression_value.hpp>
+#include <boost/wave/util/pattern_parser.hpp>
+#include <boost/wave/util/macro_helpers.hpp>
+
+#if !defined(spirit_append_actor)
+#define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor)
+#define spirit_assign_actor(actor) boost::spirit::classic::assign_a(actor)
+#endif // !defined(spirit_append_actor)
+
+// this must occur after all of the includes and before any code appears
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_PREFIX
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Encapsulation of the grammar for evaluation of constant preprocessor
+// expressions
+//
+///////////////////////////////////////////////////////////////////////////////
+namespace boost {
+namespace wave {
+namespace grammars {
+namespace closures {
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// define the closure type used throughout the C++ expression grammar
+//
+// Throughout this grammar all literal tokens are stored into a
+// closure_value variables, which converts the types appropriately, where
+// required.
+//
+///////////////////////////////////////////////////////////////////////////////
+ struct cpp_expr_closure
+ : boost::spirit::classic::closure<cpp_expr_closure, closure_value>
+ {
+ member1 val;
+ };
+
+} // namespace closures
+
+namespace impl {
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// convert the given token value (integer literal) to a unsigned long
+//
+///////////////////////////////////////////////////////////////////////////////
+ struct convert_intlit {
+
+ template <typename ArgT>
+ struct result {
+
+ typedef boost::wave::grammars::closures::closure_value type;
+ };
+
+ template <typename TokenT>
+ boost::wave::grammars::closures::closure_value
+ operator()(TokenT const &token) const
+ {
+ typedef boost::wave::grammars::closures::closure_value return_type;
+ bool is_unsigned = false;
+ uint_literal_type ul = intlit_grammar_gen<TokenT>::evaluate(token,
+ is_unsigned);
+
+ return is_unsigned ?
+ return_type(ul) : return_type(static_cast<int_literal_type>(ul));
+ }
+ };
+ phoenix::function<convert_intlit> const as_intlit;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Convert the given token value (character literal) to a unsigned int
+//
+///////////////////////////////////////////////////////////////////////////////
+ struct convert_chlit {
+
+ template <typename ArgT>
+ struct result {
+
+ typedef boost::wave::grammars::closures::closure_value type;
+ };
+
+ template <typename TokenT>
+ boost::wave::grammars::closures::closure_value
+ operator()(TokenT const &token) const
+ {
+ typedef boost::wave::grammars::closures::closure_value return_type;
+ value_error status = error_noerror;
+
+ // If the literal is a wchar_t and wchar_t is represented by a
+ // signed integral type, then the created value will be signed as
+ // well, otherwise we assume unsigned values.
+#if BOOST_WAVE_WCHAR_T_SIGNEDNESS == BOOST_WAVE_WCHAR_T_AUTOSELECT
+ if ('L' == token.get_value()[0] && std::numeric_limits<wchar_t>::is_signed)
+ {
+ int value = chlit_grammar_gen<int, TokenT>::evaluate(token, status);
+ return return_type(value, status);
+ }
+#elif BOOST_WAVE_WCHAR_T_SIGNEDNESS == BOOST_WAVE_WCHAR_T_FORCE_SIGNED
+ if ('L' == token.get_value()[0])
+ {
+ int value = chlit_grammar_gen<int, TokenT>::evaluate(token, status);
+ return return_type(value, status);
+ }
+#endif
+
+ unsigned int value = chlit_grammar_gen<unsigned int, TokenT>::evaluate(token, status);
+ return return_type(value, status);
+ }
+ };
+ phoenix::function<convert_chlit> const as_chlit;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Handle the ?: operator with correct type and error propagation
+//
+////////////////////////////////////////////////////////////////////////////////
+ struct operator_questionmark {
+
+ template <typename CondT, typename Arg1T, typename Arg2T>
+ struct result {
+
+ typedef boost::wave::grammars::closures::closure_value type;
+ };
+
+ template <typename CondT, typename Arg1T, typename Arg2T>
+ boost::wave::grammars::closures::closure_value
+ operator()(CondT const &cond, Arg1T &val1, Arg2T const &val2) const
+ {
+ return val1.handle_questionmark(cond, val2);
+ }
+ };
+ phoenix::function<operator_questionmark> const questionmark;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Handle type conversion conserving error conditions
+//
+///////////////////////////////////////////////////////////////////////////////
+ struct operator_to_bool {
+
+ template <typename ArgT>
+ struct result {
+
+ typedef boost::wave::grammars::closures::closure_value type;
+ };
+
+ template <typename ArgT>
+ boost::wave::grammars::closures::closure_value
+ operator()(ArgT &val) const
+ {
+ typedef boost::wave::grammars::closures::closure_value return_type;
+ return return_type(
+ boost::wave::grammars::closures::as_bool(val), val.is_valid());
+ }
+ };
+ phoenix::function<operator_to_bool> const to_bool;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Handle explicit type conversion
+//
+///////////////////////////////////////////////////////////////////////////////
+ struct operator_as_bool {
+
+ template <typename ArgT>
+ struct result {
+
+ typedef bool type;
+ };
+
+ template <typename ArgT>
+ bool
+ operator()(ArgT &val) const
+ {
+ return boost::wave::grammars::closures::as_bool(val);
+ }
+ };
+ phoenix::function<operator_as_bool> const as_bool;
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Handle closure value operators with proper error propagation
+//
+///////////////////////////////////////////////////////////////////////////////
+#define BOOST_WAVE_BINARYOP(op, optok) \
+ struct operator_binary_ ## op { \
+ \
+ template <typename Arg1T, typename Arg2T> \
+ struct result { \
+ \
+ typedef boost::wave::grammars::closures::closure_value type; \
+ }; \
+ \
+ template <typename Arg1T, typename Arg2T> \
+ boost::wave::grammars::closures::closure_value \
+ operator()(Arg1T &val1, Arg2T &val2) const \
+ { \
+ return val1 optok val2; \
+ } \
+ }; \
+ phoenix::function<operator_binary_ ## op> const binary_ ## op \
+ /**/
+
+ BOOST_WAVE_BINARYOP(and, &&);
+ BOOST_WAVE_BINARYOP(or, ||);
+
+ BOOST_WAVE_BINARYOP(bitand, &);
+ BOOST_WAVE_BINARYOP(bitor, |);
+ BOOST_WAVE_BINARYOP(bitxor, ^);
+
+ BOOST_WAVE_BINARYOP(lesseq, <=);
+ BOOST_WAVE_BINARYOP(less, <);
+ BOOST_WAVE_BINARYOP(greater, >);
+ BOOST_WAVE_BINARYOP(greateq, >=);
+ BOOST_WAVE_BINARYOP(eq, ==);
+ BOOST_WAVE_BINARYOP(ne, !=);
+
+#undef BOOST_WAVE_BINARYOP
+
+///////////////////////////////////////////////////////////////////////////////
+#define BOOST_WAVE_UNARYOP(op, optok) \
+ struct operator_unary_ ## op { \
+ \
+ template <typename ArgT> \
+ struct result { \
+ \
+ typedef boost::wave::grammars::closures::closure_value type; \
+ }; \
+ \
+ template <typename ArgT> \
+ boost::wave::grammars::closures::closure_value \
+ operator()(ArgT &val) const \
+ { \
+ return optok val; \
+ } \
+ }; \
+ phoenix::function<operator_unary_ ## op> const unary_ ## op \
+ /**/
+
+ BOOST_WAVE_UNARYOP(neg, !);
+
+#undef BOOST_WAVE_UNARYOP
+
+} // namespace impl
+
+///////////////////////////////////////////////////////////////////////////////
+// define, whether the rule's should generate some debug output
+#define TRACE_CPP_EXPR_GRAMMAR \
+ bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR) \
+ /**/
+
+struct expression_grammar :
+ public boost::spirit::classic::grammar<
+ expression_grammar,
+ closures::cpp_expr_closure::context_t
+ >
+{
+ expression_grammar()
+ {
+ BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "expression_grammar",
+ TRACE_CPP_EXPR_GRAMMAR);
+ }
+
+ // no need for copy constructor/assignment operator
+ expression_grammar(expression_grammar const&);
+ expression_grammar& operator= (expression_grammar const&);
+
+ template <typename ScannerT>
+ struct definition
+ {
+ typedef closures::cpp_expr_closure closure_type;
+ typedef boost::spirit::classic::rule<ScannerT, closure_type::context_t> rule_t;
+ typedef boost::spirit::classic::rule<ScannerT> simple_rule_t;
+
+ simple_rule_t pp_expression;
+
+ rule_t const_exp;
+ rule_t logical_or_exp, logical_and_exp;
+ rule_t inclusive_or_exp, exclusive_or_exp, and_exp;
+ rule_t cmp_equality, cmp_relational;
+ rule_t shift_exp;
+ rule_t add_exp, multiply_exp;
+ rule_t unary_exp, primary_exp, constant;
+
+ rule_t const_exp_nocalc;
+ rule_t logical_or_exp_nocalc, logical_and_exp_nocalc;
+ rule_t inclusive_or_exp_nocalc, exclusive_or_exp_nocalc, and_exp_nocalc;
+ rule_t cmp_equality_nocalc, cmp_relational_nocalc;
+ rule_t shift_exp_nocalc;
+ rule_t add_exp_nocalc, multiply_exp_nocalc;
+ rule_t unary_exp_nocalc, primary_exp_nocalc, constant_nocalc;
+
+ boost::spirit::classic::subrule<0, closure_type::context_t> const_exp_subrule;
+
+ definition(expression_grammar const &self)
+ {
+ using namespace boost::spirit::classic;
+ using namespace phoenix;
+ using namespace boost::wave;
+ using boost::wave::util::pattern_p;
+
+ pp_expression
+ = const_exp[self.val = arg1]
+ ;
+
+ const_exp
+ = logical_or_exp[const_exp.val = arg1]
+ >> !(const_exp_subrule =
+ ch_p(T_QUESTION_MARK)
+ >> const_exp
+ [
+ const_exp_subrule.val = arg1
+ ]
+ >> ch_p(T_COLON)
+ >> const_exp
+ [
+ const_exp_subrule.val =
+ impl::questionmark(const_exp.val,
+ const_exp_subrule.val, arg1)
+ ]
+ )[const_exp.val = arg1]
+ ;
+
+ logical_or_exp
+ = logical_and_exp[logical_or_exp.val = arg1]
+ >> *( if_p(impl::as_bool(logical_or_exp.val))
+ [
+ // if one of the || operators is true, no more
+ // evaluation is required
+ pattern_p(T_OROR, MainTokenMask)
+ >> logical_and_exp_nocalc
+ [
+ logical_or_exp.val =
+ impl::to_bool(logical_or_exp.val)
+ ]
+ ]
+ .else_p
+ [
+ pattern_p(T_OROR, MainTokenMask)
+ >> logical_and_exp
+ [
+ logical_or_exp.val =
+ impl::binary_or(logical_or_exp.val, arg1)
+ ]
+ ]
+ )
+ ;
+
+ logical_and_exp
+ = inclusive_or_exp[logical_and_exp.val = arg1]
+ >> *( if_p(impl::as_bool(logical_and_exp.val))
+ [
+ pattern_p(T_ANDAND, MainTokenMask)
+ >> inclusive_or_exp
+ [
+ logical_and_exp.val =
+ impl::binary_and(logical_and_exp.val, arg1)
+ ]
+ ]
+ .else_p
+ [
+ // if one of the && operators is false, no more
+ // evaluation is required
+ pattern_p(T_ANDAND, MainTokenMask)
+ >> inclusive_or_exp_nocalc
+ [
+ logical_and_exp.val =
+ impl::to_bool(logical_and_exp.val)
+ ]
+ ]
+ )
+ ;
+
+ inclusive_or_exp
+ = exclusive_or_exp[inclusive_or_exp.val = arg1]
+ >> *( pattern_p(T_OR, MainTokenMask)
+ >> exclusive_or_exp
+ [
+ inclusive_or_exp.val =
+ impl::binary_bitor(inclusive_or_exp.val, arg1)
+ ]
+ )
+ ;
+
+ exclusive_or_exp
+ = and_exp[exclusive_or_exp.val = arg1]
+ >> *( pattern_p(T_XOR, MainTokenMask)
+ >> and_exp
+ [
+ exclusive_or_exp.val =
+ impl::binary_bitxor(exclusive_or_exp.val, arg1)
+ ]
+ )
+ ;
+
+ and_exp
+ = cmp_equality[and_exp.val = arg1]
+ >> *( pattern_p(T_AND, MainTokenMask)
+ >> cmp_equality
+ [
+ and_exp.val =
+ impl::binary_bitand(and_exp.val, arg1)
+ ]
+ )
+ ;
+
+ cmp_equality
+ = cmp_relational[cmp_equality.val = arg1]
+ >> *( ch_p(T_EQUAL)
+ >> cmp_relational
+ [
+ cmp_equality.val =
+ impl::binary_eq(cmp_equality.val, arg1)
+ ]
+ | pattern_p(T_NOTEQUAL, MainTokenMask)
+ >> cmp_relational
+ [
+ cmp_equality.val =
+ impl::binary_ne(cmp_equality.val, arg1)
+ ]
+ )
+ ;
+
+ cmp_relational
+ = shift_exp[cmp_relational.val = arg1]
+ >> *( ch_p(T_LESSEQUAL)
+ >> shift_exp
+ [
+ cmp_relational.val =
+ impl::binary_lesseq(cmp_relational.val, arg1)
+ ]
+ | ch_p(T_GREATEREQUAL)
+ >> shift_exp
+ [
+ cmp_relational.val =
+ impl::binary_greateq(cmp_relational.val, arg1)
+ ]
+ | ch_p(T_LESS)
+ >> shift_exp
+ [
+ cmp_relational.val =
+ impl::binary_less(cmp_relational.val, arg1)
+ ]
+ | ch_p(T_GREATER)
+ >> shift_exp
+ [
+ cmp_relational.val =
+ impl::binary_greater(cmp_relational.val, arg1)
+ ]
+ )
+ ;
+
+ shift_exp
+ = add_exp[shift_exp.val = arg1]
+ >> *( ch_p(T_SHIFTLEFT)
+ >> add_exp
+ [
+ shift_exp.val <<= arg1
+ ]
+ | ch_p(T_SHIFTRIGHT)
+ >> add_exp
+ [
+ shift_exp.val >>= arg1
+ ]
+ )
+ ;
+
+ add_exp
+ = multiply_exp[add_exp.val = arg1]
+ >> *( ch_p(T_PLUS)
+ >> multiply_exp
+ [
+ add_exp.val += arg1
+ ]
+ | ch_p(T_MINUS)
+ >> multiply_exp
+ [
+ add_exp.val -= arg1
+ ]
+ )
+ ;
+
+ multiply_exp
+ = unary_exp[multiply_exp.val = arg1]
+ >> *( ch_p(T_STAR)
+ >> unary_exp
+ [
+ multiply_exp.val *= arg1
+ ]
+ | ch_p(T_DIVIDE)
+ >> unary_exp
+ [
+ multiply_exp.val /= arg1
+ ]
+ | ch_p(T_PERCENT)
+ >> unary_exp
+ [
+ multiply_exp.val %= arg1
+ ]
+ )
+ ;
+
+ unary_exp
+ = primary_exp[unary_exp.val = arg1]
+ | ch_p(T_PLUS) >> unary_exp
+ [
+ unary_exp.val = arg1
+ ]
+ | ch_p(T_MINUS) >> unary_exp
+ [
+ unary_exp.val = -arg1
+ ]
+ | pattern_p(T_COMPL, MainTokenMask) >> unary_exp
+ [
+ unary_exp.val = ~arg1
+ ]
+ | pattern_p(T_NOT, MainTokenMask) >> unary_exp
+ [
+ unary_exp.val = impl::unary_neg(arg1)
+ ]
+ ;
+
+ primary_exp
+ = constant[primary_exp.val = arg1]
+ | ch_p(T_LEFTPAREN)
+ >> const_exp[primary_exp.val = arg1]
+ >> ch_p(T_RIGHTPAREN)
+ ;
+
+ constant
+ = ch_p(T_PP_NUMBER)
+ [
+ constant.val = impl::as_intlit(arg1)
+ ]
+ | ch_p(T_INTLIT)
+ [
+ constant.val = impl::as_intlit(arg1)
+ ]
+ | ch_p(T_CHARLIT)
+ [
+ constant.val = impl::as_chlit(arg1)
+ ]
+ ;
+
+ // here follows the same grammar, but without any embedded
+ // calculations
+ const_exp_nocalc
+ = logical_or_exp_nocalc
+ >> !( ch_p(T_QUESTION_MARK)
+ >> const_exp_nocalc
+ >> ch_p(T_COLON)
+ >> const_exp_nocalc
+ )
+ ;
+
+ logical_or_exp_nocalc
+ = logical_and_exp_nocalc
+ >> *( pattern_p(T_OROR, MainTokenMask)
+ >> logical_and_exp_nocalc
+ )
+ ;
+
+ logical_and_exp_nocalc
+ = inclusive_or_exp_nocalc
+ >> *( pattern_p(T_ANDAND, MainTokenMask)
+ >> inclusive_or_exp_nocalc
+ )
+ ;
+
+ inclusive_or_exp_nocalc
+ = exclusive_or_exp_nocalc
+ >> *( pattern_p(T_OR, MainTokenMask)
+ >> exclusive_or_exp_nocalc
+ )
+ ;
+
+ exclusive_or_exp_nocalc
+ = and_exp_nocalc
+ >> *( pattern_p(T_XOR, MainTokenMask)
+ >> and_exp_nocalc
+ )
+ ;
+
+ and_exp_nocalc
+ = cmp_equality_nocalc
+ >> *( pattern_p(T_AND, MainTokenMask)
+ >> cmp_equality_nocalc
+ )
+ ;
+
+ cmp_equality_nocalc
+ = cmp_relational_nocalc
+ >> *( ch_p(T_EQUAL)
+ >> cmp_relational_nocalc
+ | pattern_p(T_NOTEQUAL, MainTokenMask)
+ >> cmp_relational_nocalc
+ )
+ ;
+
+ cmp_relational_nocalc
+ = shift_exp_nocalc
+ >> *( ch_p(T_LESSEQUAL)
+ >> shift_exp_nocalc
+ | ch_p(T_GREATEREQUAL)
+ >> shift_exp_nocalc
+ | ch_p(T_LESS)
+ >> shift_exp_nocalc
+ | ch_p(T_GREATER)
+ >> shift_exp_nocalc
+ )
+ ;
+
+ shift_exp_nocalc
+ = add_exp_nocalc
+ >> *( ch_p(T_SHIFTLEFT)
+ >> add_exp_nocalc
+ | ch_p(T_SHIFTRIGHT)
+ >> add_exp_nocalc
+ )
+ ;
+
+ add_exp_nocalc
+ = multiply_exp_nocalc
+ >> *( ch_p(T_PLUS)
+ >> multiply_exp_nocalc
+ | ch_p(T_MINUS)
+ >> multiply_exp_nocalc
+ )
+ ;
+
+ multiply_exp_nocalc
+ = unary_exp_nocalc
+ >> *( ch_p(T_STAR)
+ >> unary_exp_nocalc
+ | ch_p(T_DIVIDE)
+ >> unary_exp_nocalc
+ | ch_p(T_PERCENT)
+ >> unary_exp_nocalc
+ )
+ ;
+
+ unary_exp_nocalc
+ = primary_exp_nocalc
+ | ch_p(T_PLUS) >> unary_exp_nocalc
+ | ch_p(T_MINUS) >> unary_exp_nocalc
+ | pattern_p(T_COMPL, MainTokenMask) >> unary_exp_nocalc
+ | pattern_p(T_NOT, MainTokenMask) >> unary_exp_nocalc
+ ;
+
+ primary_exp_nocalc
+ = constant_nocalc
+ | ch_p(T_LEFTPAREN)
+ >> const_exp_nocalc
+ >> ch_p(T_RIGHTPAREN)
+ ;
+
+ constant_nocalc
+ = ch_p(T_PP_NUMBER)
+ | ch_p(T_INTLIT)
+ | ch_p(T_CHARLIT)
+ ;
+
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(pp_expression, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_or_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_and_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(inclusive_or_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(exclusive_or_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(and_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_equality, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_relational, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(shift_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(add_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(multiply_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(unary_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(primary_exp, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(constant, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp_subrule, TRACE_CPP_EXPR_GRAMMAR);
+
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(const_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(logical_and_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(inclusive_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(exclusive_or_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(and_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_equality_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(cmp_relational_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(shift_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(add_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(multiply_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(unary_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(primary_exp_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ BOOST_SPIRIT_DEBUG_TRACE_RULE(constant_nocalc, TRACE_CPP_EXPR_GRAMMAR);
+ }
+
+ // start rule of this grammar
+ simple_rule_t const& start() const
+ { return pp_expression; }
+ };
+};
+
+///////////////////////////////////////////////////////////////////////////////
+#undef TRACE_CPP_EXPR_GRAMMAR
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// The following function is defined here, to allow the separation of
+// the compilation of the expression_grammar from the function using it.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
+#define BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
+#else
+#define BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE inline
+#endif
+
+template <typename TokenT>
+BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
+bool
+expression_grammar_gen<TokenT>::evaluate(
+ typename token_sequence_type::const_iterator const &first,
+ typename token_sequence_type::const_iterator const &last,
+ typename token_type::position_type const &act_pos,
+ bool if_block_status, value_error &status)
+{
+ using namespace boost::spirit::classic;
+ using namespace boost::wave;
+ using namespace boost::wave::grammars::closures;
+
+ using boost::wave::util::impl::as_string;
+
+ typedef typename token_sequence_type::const_iterator iterator_type;
+ typedef typename token_sequence_type::value_type::string_type string_type;
+
+ parse_info<iterator_type> hit(first);
+ closure_value result; // expression result
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+ try
+#endif
+ {
+ expression_grammar g; // expression grammar
+ hit = parse (first, last, g[spirit_assign_actor(result)],
+ ch_p(T_SPACE) | ch_p(T_CCOMMENT) | ch_p(T_CPPCOMMENT));
+
+ if (!hit.hit) {
+ // expression is illformed
+ if (if_block_status) {
+ string_type expression = as_string<string_type>(first, last);
+ if (0 == expression.size())
+ expression = "<empty expression>";
+ BOOST_WAVE_THROW(preprocess_exception, ill_formed_expression,
+ expression.c_str(), act_pos);
+ return false;
+ }
+ else {
+ // as the if_block_status is false no errors will be reported
+ return false;
+ }
+ }
+ }
+#if !defined(BOOST_NO_EXCEPTIONS)
+ catch (boost::wave::preprocess_exception const& e) {
+ // expression is illformed
+ if (if_block_status) {
+ boost::throw_exception(e);
+ return false;
+ }
+ else {
+ // as the if_block_status is false no errors will be reported
+ return false;
+ }
+ }
+#endif
+
+ if (!hit.full) {
+ // The token list starts with a valid expression, but there remains
+ // something. If the remainder consists out of whitespace only, the
+ // expression is still valid.
+ iterator_type next = hit.stop;
+
+ while (next != last) {
+ switch (static_cast<unsigned int>(token_id(*next))) {
+ case T_SPACE:
+ case T_SPACE2:
+ case T_CCOMMENT:
+ break; // ok continue
+
+ case T_NEWLINE:
+ case T_EOF:
+ case T_CPPCOMMENT: // contains newline
+ return as_bool(result); // expression is valid
+
+ default:
+ // expression is illformed
+ if (if_block_status) {
+ string_type expression = as_string<string_type>(first, last);
+ if (0 == expression.size())
+ expression = "<empty expression>";
+ BOOST_WAVE_THROW(preprocess_exception, ill_formed_expression,
+ expression.c_str(), act_pos);
+ return false;
+ }
+ else {
+ // as the if_block_status is false no errors will be reported
+ return false;
+ }
+ }
+ ++next;
+ }
+ }
+
+ if (error_noerror != result.is_valid()) // division or other error by zero occurred
+ status = result.is_valid();
+
+// token sequence is a valid expression
+ return as_bool(result);
+}
+
+#undef BOOST_WAVE_EXPRGRAMMAR_GEN_INLINE
+
+///////////////////////////////////////////////////////////////////////////////
+} // namespace grammars
+} // namespace wave
+} // namespace boost
+
+// the suffix header occurs after all of the code
+#ifdef BOOST_HAS_ABI_HEADERS
+#include BOOST_ABI_SUFFIX
+#endif
+
+#endif // !defined(CPP_EXPRESSION_GRAMMAR_HPP_099CD1A4_A6C0_44BE_8F24_0B00F5BE5674_INCLUDED)