| /*============================================================================= |
| Boost.Wave: A Standard compliant C++ preprocessor library |
| |
| http://www.boost.org/ |
| |
| 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(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; |
| unsigned int value = chlit_grammar_gen<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) |