⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpp_expression_grammar.hpp

📁 C++的一个好库。。。现在很流行
💻 HPP
📖 第 1 页 / 共 2 页
字号:
/*=============================================================================
    Boost.Wave: A Standard compliant C++ preprocessor library

    http://www.boost.org/

    Copyright (c) 2001-2005 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/assert.hpp>
#include <boost/spirit/core.hpp>
#include <boost/spirit/attribute/closure.hpp>
#include <boost/spirit/dynamic/if.hpp>
#if SPIRIT_VERSION >= 0x1700
#include <boost/spirit/actor/assign_actor.hpp>
#include <boost/spirit/actor/push_back_actor.hpp>
#endif // SPIRIT_VERSION >= 0x1700

#include <boost/spirit/phoenix/functions.hpp>
#include <boost/spirit/phoenix/operators.hpp>
#include <boost/spirit/phoenix/primitives.hpp>
#include <boost/spirit/phoenix/statements.hpp>
#include <boost/spirit/phoenix/casts.hpp>

#include <boost/wave/wave_config.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)
#if SPIRIT_VERSION >= 0x1700
#define spirit_append_actor(actor) boost::spirit::push_back_a(actor)
#define spirit_assign_actor(actor) boost::spirit::assign_a(actor)
#else
#define spirit_append_actor(actor) boost::spirit::append(actor)
#define spirit_assign_actor(actor) boost::spirit::assign(actor)
#endif // SPIRIT_VERSION >= 0x1700
#endif // !defined(spirit_append_actor)

///////////////////////////////////////////////////////////////////////////////
//
//  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::closure<cpp_expr_closure, closure_value> 
    {
        member1 val;
    };

}   // namespace closures

namespace impl {

///////////////////////////////////////////////////////////////////////////////
//
//  convert the given tokenvalue (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_t;
            bool is_unsigned = false;
            unsigned long ul = intlit_grammar_gen<TokenT>::evaluate(token, 
                is_unsigned);

            return is_unsigned ? return_t(ul) : return_t(static_cast<long>(ul));
        }
    };
    phoenix::function<convert_intlit> const as_intlit;

///////////////////////////////////////////////////////////////////////////////
//
//  convert the given tokenvalue (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_t;
            return return_t(chlit_grammar_gen<TokenT>::evaluate(token));
        }
    };
    phoenix::function<convert_chlit> const as_chlit;

////////////////////////////////////////////////////////////////////////////////
//
//  Handle the ?: operator with correct type 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
        { 
            typedef boost::wave::grammars::closures::closure_value return_t;
            return return_t(val1.handle_questionmark(cond, val2));
        }
    };
    phoenix::function<operator_questionmark> const questionmark;
    
}   // 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::grammar<
        expression_grammar, 
        closures::cpp_expr_closure::context_t
    >
{
    expression_grammar()
    {
        BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "expression_grammar", 
            TRACE_CPP_EXPR_GRAMMAR);
    }
    
    template <typename ScannerT>
    struct definition
    {
        typedef closures::cpp_expr_closure closure_type;
        typedef boost::spirit::rule<ScannerT, closure_type::context_t> rule_t;
        typedef boost::spirit::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::subrule<0, closure_type::context_t> const_exp_subrule;

        definition(expression_grammar const &self)
        {
            using namespace boost::spirit;
            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(static_cast_<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 = 
                                            static_cast_<bool>(logical_or_exp.val)
                                    ]
                            ]
                            .else_p
                            [
                                pattern_p(T_OROR, MainTokenMask)
                                >>  logical_and_exp
                                    [
                                        logical_or_exp.val = 
                                            logical_or_exp.val || arg1
                                    ]
                            ]
                        )
                ;

            logical_and_exp
                =   inclusive_or_exp[logical_and_exp.val = arg1]
                    >> *(   if_p(static_cast_<bool>(logical_and_exp.val))
                            [
                                pattern_p(T_ANDAND, MainTokenMask)
                                >>  inclusive_or_exp
                                    [
                                        logical_and_exp.val = 
                                            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 =
                                            static_cast_<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 = 
                                          static_cast_<unsigned int>(inclusive_or_exp.val) 
                                      |   static_cast_<unsigned int>(arg1)
                                ]
                        )
                ;

            exclusive_or_exp
                =   and_exp[exclusive_or_exp.val = arg1]
                    >> *(   pattern_p(T_XOR, MainTokenMask)
                            >>  and_exp
                                [
                                    exclusive_or_exp.val = 
                                          static_cast_<unsigned int>(exclusive_or_exp.val)
                                      ^   static_cast_<unsigned int>(arg1)
                                ]
                        )
                ;

            and_exp
                =   cmp_equality[and_exp.val = arg1]
                    >> *(   pattern_p(T_AND, MainTokenMask)
                            >>  cmp_equality
                                [
                                    and_exp.val = 
                                          static_cast_<unsigned int>(and_exp.val)
                                      &   static_cast_<unsigned int>(arg1)
                                ]
                        )
                ;

            cmp_equality
                =   cmp_relational[cmp_equality.val = arg1]
                    >> *(   ch_p(T_EQUAL)
                            >>  cmp_relational
                                [
                                    cmp_equality.val = 
                                        cmp_equality.val == arg1
                                ]
                        |   pattern_p(T_NOTEQUAL, MainTokenMask)
                            >>  cmp_relational
                                [
                                    cmp_equality.val = 
                                        cmp_equality.val != arg1
                                ]
                        )
                ;

            cmp_relational
                =   shift_exp[cmp_relational.val = arg1]
                    >> *(   ch_p(T_LESSEQUAL)
                            >>  shift_exp
                                [
                                    cmp_relational.val = 
                                        cmp_relational.val <= arg1
                                ]
                        |   ch_p(T_GREATEREQUAL)
                            >>  shift_exp
                                [
                                    cmp_relational.val = 
                                        cmp_relational.val >= arg1
                                ]
                        |   ch_p(T_LESS)
                            >>  shift_exp
                                [
                                    cmp_relational.val = 
                                        cmp_relational.val < arg1
                                ]
                        |   ch_p(T_GREATER)
                            >>  shift_exp
                                [
                                    cmp_relational.val = 
                                        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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -