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