📄 cpp_expression_grammar.hpp
字号:
/*=============================================================================
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 + -