blob: 0edc8853d5e1de2ceebe9699b8d5100ea8c84e1a [file] [log] [blame]
/*=============================================================================
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_PREDEF_MACROS_GRAMMAR_HPP_53858C9A_C202_4D60_AD92_DC9CAE4DBB43_INCLUDED)
#define CPP_PREDEF_MACROS_GRAMMAR_HPP_53858C9A_C202_4D60_AD92_DC9CAE4DBB43_INCLUDED
#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_parse_tree.hpp>
#include <boost/spirit/include/classic_confix.hpp>
#include <boost/spirit/include/classic_lists.hpp>
#include <boost/wave/wave_config.hpp>
#include <boost/wave/token_ids.hpp>
#include <boost/wave/grammars/cpp_predef_macros_gen.hpp>
#include <boost/wave/util/pattern_parser.hpp>
// this must occur after all of the includes and before any code appears
#ifdef BOOST_HAS_ABI_HEADERS
#include BOOST_ABI_PREFIX
#endif
///////////////////////////////////////////////////////////////////////////////
namespace boost {
namespace wave {
namespace grammars {
///////////////////////////////////////////////////////////////////////////////
// define, whether the rule's should generate some debug output
#define TRACE_PREDEF_MACROS_GRAMMAR \
bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_PREDEF_MACROS_GRAMMAR) \
/**/
///////////////////////////////////////////////////////////////////////////////
// Encapsulation of the grammar for command line driven predefined macros.
struct predefined_macros_grammar :
public boost::spirit::classic::grammar<predefined_macros_grammar>
{
template <typename ScannerT>
struct definition
{
// 'normal' (parse_tree generating) rule type
typedef boost::spirit::classic::rule<
ScannerT, boost::spirit::classic::dynamic_parser_tag>
rule_type;
rule_type plain_define, macro_definition, macro_parameters;
definition(predefined_macros_grammar const &/*self*/)
{
// import the spirit and cpplexer namespaces here
using namespace boost::spirit::classic;
using namespace boost::wave;
using namespace boost::wave::util;
// set the rule id's for later use
plain_define.set_id(BOOST_WAVE_PLAIN_DEFINE_ID);
macro_parameters.set_id(BOOST_WAVE_MACRO_PARAMETERS_ID);
macro_definition.set_id(BOOST_WAVE_MACRO_DEFINITION_ID);
// recognizes command line defined macro syntax, i.e.
// -DMACRO
// -DMACRO=
// -DMACRO=value
// -DMACRO(x)
// -DMACRO(x)=
// -DMACRO(x)=value
// This grammar resembles the overall structure of the cpp_grammar to
// make it possible to reuse the parse tree traversal code
plain_define
= ( ch_p(T_IDENTIFIER)
| pattern_p(KeywordTokenType,
TokenTypeMask|PPTokenFlag)
| pattern_p(OperatorTokenType|AltExtTokenType,
ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc.
| pattern_p(BoolLiteralTokenType,
TokenTypeMask|PPTokenFlag) // true/false
)
>> !macro_parameters
>> !macro_definition
;
// parameter list
macro_parameters
= confix_p(
no_node_d[ch_p(T_LEFTPAREN) >> *ch_p(T_SPACE)],
!list_p(
( ch_p(T_IDENTIFIER)
| pattern_p(KeywordTokenType,
TokenTypeMask|PPTokenFlag)
| pattern_p(OperatorTokenType|AltExtTokenType,
ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc.
| pattern_p(BoolLiteralTokenType,
TokenTypeMask|PPTokenFlag) // true/false
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
| ch_p(T_ELLIPSIS)
#endif
),
no_node_d
[
*ch_p(T_SPACE) >> ch_p(T_COMMA) >> *ch_p(T_SPACE)
]
),
no_node_d[*ch_p(T_SPACE) >> ch_p(T_RIGHTPAREN)]
)
;
// macro body (anything left until eol)
macro_definition
= no_node_d[ch_p(T_ASSIGN)]
>> *anychar_p
;
BOOST_SPIRIT_DEBUG_TRACE_RULE(plain_define, TRACE_PREDEF_MACROS_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_definition, TRACE_PREDEF_MACROS_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_parameters, TRACE_PREDEF_MACROS_GRAMMAR);
}
// start rule of this grammar
rule_type const& start() const
{ return plain_define; }
};
predefined_macros_grammar()
{
BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this,
"predefined_macros_grammar", TRACE_PREDEF_MACROS_GRAMMAR);
}
};
///////////////////////////////////////////////////////////////////////////////
#undef TRACE_PREDEF_MACROS_GRAMMAR
///////////////////////////////////////////////////////////////////////////////
//
// The following parse function is defined here, to allow the separation of
// the compilation of the cpp_predefined_macros_grammar from the function
// using it.
//
///////////////////////////////////////////////////////////////////////////////
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
#define BOOST_WAVE_PREDEF_MACROS_GRAMMAR_GEN_INLINE
#else
#define BOOST_WAVE_PREDEF_MACROS_GRAMMAR_GEN_INLINE inline
#endif
template <typename LexIteratorT>
BOOST_WAVE_PREDEF_MACROS_GRAMMAR_GEN_INLINE
boost::spirit::classic::tree_parse_info<LexIteratorT>
predefined_macros_grammar_gen<LexIteratorT>::parse_predefined_macro (
LexIteratorT const &first, LexIteratorT const &last)
{
predefined_macros_grammar g;
return boost::spirit::classic::pt_parse (first, last, g);
}
#undef BOOST_WAVE_PREDEF_MACROS_GRAMMAR_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_PREDEF_MACROS_GRAMMAR_HPP_53858C9A_C202_4D60_AD92_DC9CAE4DBB43_INCLUDED)