mirror of
https://github.com/boostorg/wave.git
synced 2026-02-22 15:52:22 +00:00
Added Wave review candidate to repository.
[SVN r1909]
This commit is contained in:
31
samples/cpp_tokens/build/Jamfile
Normal file
31
samples/cpp_tokens/build/Jamfile
Normal file
@@ -0,0 +1,31 @@
|
||||
# Wave: A Standard compliant C++ preprocessor library
|
||||
#
|
||||
# Boost Wave Library Sample Build Jamfile (cpp_tokens)
|
||||
#
|
||||
# Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
# http://spirit.sourceforge.net/
|
||||
#
|
||||
# Use, modification, and distribution is subject to 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)
|
||||
|
||||
subproject libs/wave/samples/cpp_tokens/build ;
|
||||
|
||||
exe cpp_tokens
|
||||
: ../cpp_tokens.cpp
|
||||
../instantiate_cpp_exprgrammar.cpp
|
||||
../instantiate_cpp_grammar.cpp
|
||||
../instantiate_cpp_literalgrammars.cpp
|
||||
../instantiate_defined_grammar.cpp
|
||||
../instantiate_slex_lexer.cpp
|
||||
<lib>../../../build/boost_wave
|
||||
<lib>../../../../../libs/program_options/build/boost_program_options
|
||||
<lib>../../../../../libs/filesystem/build/boost_filesystem
|
||||
:
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<vc7.1><*><rtti>off # workaround for compiler bug
|
||||
:
|
||||
<runtime-link>static
|
||||
<threading>single
|
||||
;
|
||||
|
||||
28
samples/cpp_tokens/build/Jamfile.v2
Normal file
28
samples/cpp_tokens/build/Jamfile.v2
Normal file
@@ -0,0 +1,28 @@
|
||||
# Wave: A Standard compliant C++ preprocessor library
|
||||
#
|
||||
# Boost Wave Library Sample Build Jamfile (list_includes)
|
||||
#
|
||||
# Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
# http://spirit.sourceforge.net/
|
||||
#
|
||||
# Use, modification, and distribution is subject to 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)
|
||||
|
||||
exe cpp_tokens
|
||||
: ../cpp_tokens.cpp
|
||||
../instantiate_cpp_exprgrammar.cpp
|
||||
../instantiate_cpp_grammar.cpp
|
||||
../instantiate_cpp_literalgrammars.cpp
|
||||
../instantiate_defined_grammar.cpp
|
||||
../instantiate_slex_lexer.cpp
|
||||
<lib>../../../build/boost_wave
|
||||
<lib>../../../../../libs/program_options/build/boost_program_options
|
||||
<lib>../../../../../libs/filesystem/build/boost_filesystem
|
||||
:
|
||||
<vc7.1><*><rtti>off # workaround for compiler bug
|
||||
:
|
||||
<runtime-link>static
|
||||
<threading>single
|
||||
;
|
||||
|
||||
132
samples/cpp_tokens/cpp_tokens.cpp
Normal file
132
samples/cpp_tokens/cpp_tokens.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: Print out the preprocessed tokens returned by the Wave iterator
|
||||
|
||||
This sample shows, how it is possible to use a custom lexer type and a
|
||||
custom token type with the Wave library.
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "cpp_tokens.hpp" // global configuration
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Include Wave itself
|
||||
#include <boost/wave.hpp>
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The follwoing files contain the custom lexer type to use
|
||||
#include "slex_token.hpp"
|
||||
#include "slex_iterator.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include lexer specifics, import lexer names
|
||||
#if !defined(BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION)
|
||||
#include "slex/cpp_slex_lexer.hpp"
|
||||
#endif // !defined(BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// import required names
|
||||
using namespace boost::spirit;
|
||||
|
||||
using std::string;
|
||||
using std::getline;
|
||||
using std::ifstream;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::ostream;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// main program
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (2 != argc) {
|
||||
cout << "Usage: cpp_tokens input_file" << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// read the file to analyse into a std::string
|
||||
ifstream infile(argv[1]);
|
||||
string teststr;
|
||||
if (infile.is_open()) {
|
||||
infile.unsetf(std::ios::skipws);
|
||||
string line;
|
||||
for (getline(infile, line); infile.good(); getline(infile, line)) {
|
||||
teststr += line;
|
||||
teststr += '\n';
|
||||
}
|
||||
}
|
||||
else {
|
||||
teststr = argv[1];
|
||||
}
|
||||
|
||||
// The following typedef does the trick. It defines the context type to use,
|
||||
// which depends on the lexer type (provided by the second template
|
||||
// parameter). Our lexer type 'slex_iterator<>' depends on a custom token type
|
||||
// 'slex_token<>'. Our custom token type differs from the original one povided
|
||||
// by the Wave library only by defining an addition operator<<, which is used
|
||||
// to dump the token information carried by a given token (see loop below).
|
||||
typedef boost::wave::cpp_token_sample::slex_token<> token_t;
|
||||
typedef boost::wave::cpp_token_sample::slex_iterator<token_t>
|
||||
lex_iterator_t;
|
||||
typedef boost::wave::context<std::string::iterator, lex_iterator_t>
|
||||
context_t;
|
||||
|
||||
// The C++ preprocessor iterator shouldn't be constructed directly. It is to be
|
||||
// generated through a boost::wave::context<> object. This object is
|
||||
// additionally to be used to initialize and define different parameters of
|
||||
// the actual preprocessing.
|
||||
// The preprocessing of the input stream is done on the fly behind the scenes
|
||||
// during iteration over the context_t::iterator_t stream.
|
||||
context_t ctx (teststr.begin(), teststr.end(), argv[1]);
|
||||
context_t::iterator_t first = ctx.begin();
|
||||
context_t::iterator_t last = ctx.end();
|
||||
context_t::token_t current_token;
|
||||
|
||||
try {
|
||||
// Traverse over the tokens generated from the input and dump the token
|
||||
// contents.
|
||||
while (first != last) {
|
||||
// retrieve next token
|
||||
current_token = *first;
|
||||
|
||||
// output token info
|
||||
cout << "matched " << current_token << endl;
|
||||
++first;
|
||||
}
|
||||
}
|
||||
catch (boost::wave::cpp_exception &e) {
|
||||
// some preprocessing error
|
||||
cerr
|
||||
<< e.file_name() << "(" << e.line_no() << "): "
|
||||
<< e.description() << endl;
|
||||
return 2;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
// use last recognized token to retrieve the error position
|
||||
cerr
|
||||
<< current_token.get_position().get_file()
|
||||
<< "(" << current_token.get_position().get_line() << "): "
|
||||
<< "unexpected exception: " << e.what()
|
||||
<< endl;
|
||||
return 3;
|
||||
}
|
||||
catch (...) {
|
||||
// use last recognized token to retrieve the error position
|
||||
cerr
|
||||
<< current_token.get_position().get_file()
|
||||
<< "(" << current_token.get_position().get_line() << "): "
|
||||
<< "unexpected exception." << endl;
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
39
samples/cpp_tokens/cpp_tokens.hpp
Normal file
39
samples/cpp_tokens/cpp_tokens.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: Print out the preprocessed tokens returned by the Wave iterator
|
||||
|
||||
This sample shows, how it is possible to use a custom lexer object and a
|
||||
custom token type with the Wave library.
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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_TOKENS_HPP_D6A31137_CE14_4869_9779_6357E2C43187_INCLUDED)
|
||||
#define CPP_TOKENS_HPP_D6A31137_CE14_4869_9779_6357E2C43187_INCLUDED
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include often used files from the stdlib
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include boost config
|
||||
#include <boost/config.hpp> // global configuration information
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// configure this app here (global configuration constants)
|
||||
#include "cpp_tokens_config.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include required boost libraries
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/pool/pool_alloc.hpp>
|
||||
|
||||
#endif // !defined(CPP_TOKENS_HPP_D6A31137_CE14_4869_9779_6357E2C43187_INCLUDED)
|
||||
226
samples/cpp_tokens/cpp_tokens_config.hpp
Normal file
226
samples/cpp_tokens/cpp_tokens_config.hpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: Print out the preprocessed tokens returned by the Wave iterator
|
||||
Configuration data
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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_TOKENS_HPP_7C0F1F14_6ACA_4439_A073_32C61C0DB6C5_INCLUDED)
|
||||
#define CPP_TOKENS_HPP_7C0F1F14_6ACA_4439_A073_32C61C0DB6C5_INCLUDED
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement macro scopes (#scope/#endscope), variadics,
|
||||
// placemarkers and well defined token pasting in C++ mode
|
||||
//
|
||||
// To implement these features, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define the macro scoping keywords to be used for the experimental macro
|
||||
// scoping support.
|
||||
//
|
||||
// If the following macros aren't defined, the corresponding default value is
|
||||
// used.
|
||||
//
|
||||
//#define BOOST_WAVE_PP_REGION "region"
|
||||
//#define BOOST_WAVE_PP_REGION_UC "REGION" // uppercase of BOOST_WAVE_PP_REGION
|
||||
//#define BOOST_WAVE_PP_ENDREGION "endregion"
|
||||
//#define BOOST_WAVE_PP_IMPORT "import"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define the maximal include nesting depth allowed. If this value isn't
|
||||
// defined it defaults to 1024
|
||||
//
|
||||
// To define a new initial include nesting depth uncomment the following and
|
||||
// supply a new integer value.
|
||||
//
|
||||
//#define BOOST_WAVE_MAX_INCLUDE_LEVEL_DEPTH 1024
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to support variadics and placemarkers
|
||||
//
|
||||
// To implement support variadics and placemarkers uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement a #warning directive as
|
||||
//
|
||||
// To implement #warning directives, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement #pragma once
|
||||
//
|
||||
// To implement #pragma once, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_PRAGMA_ONCE 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement #include_next
|
||||
// Please note, that this is an extension to the C++ Standard.
|
||||
//
|
||||
// To implement #include_next, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_INCLUDE_NEXT 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Undefine the following, to enable some MS specific language extensions:
|
||||
// __int8, __int16, __int32, __int64, __based, __declspec, __cdecl,
|
||||
// __fastcall, __stdcall, __try, __except, __finally, __leave, __inline,
|
||||
// __asm
|
||||
#define BOOST_WAVE_SUPPORT_MS_EXTENSIONS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the message body of the #error and #warning directives to be
|
||||
// preprocessed before the diagnostic is issued.
|
||||
//
|
||||
// Uncommenting the following will preprocess the message bodies of #error and
|
||||
// #warning messages before the error (warning) is issued
|
||||
//
|
||||
#define BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the #pragma directives to be returned to the caller (optionally after
|
||||
// preprocessing the body)
|
||||
//
|
||||
// Undefining the following will skip #pragma directives, so that the caller
|
||||
// will not see them.
|
||||
//
|
||||
#define BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the body of a #pragma directive to be preprocessed before the
|
||||
// directive is returned to the caller.
|
||||
//
|
||||
// Uncommenting the following will preprocess the bodies of #pragma directives
|
||||
//
|
||||
#define BOOST_WAVE_PREPROCESS_PRAGMA_BODY 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow to define macros with the command line syntax (-DMACRO(x)=definition)
|
||||
//
|
||||
// Uncommenting the following will enable the possibility to define macros
|
||||
// based on the command line syntax
|
||||
//
|
||||
#define BOOST_WAVE_ENABLE_COMMANDLINE_MACROS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define the string type to be used to store the token values and the file
|
||||
// names inside a file_position template class
|
||||
//
|
||||
|
||||
// use the following, if you have a fast std::allocator<char>
|
||||
#define BOOST_WAVE_STRINGTYPE wave::util::flex_string< \
|
||||
char, std::char_traits<char>, std::allocator<char>, \
|
||||
wave::util::CowString</*char,*/ \
|
||||
wave::util::AllocatorStringStorage<char> > \
|
||||
> \
|
||||
/**/
|
||||
#include <boost/wave/util/flex_string.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment the following, if you need debug output, the
|
||||
// BOOST_SPIRIT_DEBUG_FLAGS constants below help to fine control the amount of
|
||||
// the generated debug output
|
||||
//#define BOOST_SPIRIT_DEBUG
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// debug rules, subrules and grammars only, for possible flags see
|
||||
// spirit/debug.hpp
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
|
||||
#define BOOST_SPIRIT_DEBUG_FLAGS ( \
|
||||
BOOST_SPIRIT_DEBUG_FLAGS_NODES | \
|
||||
BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES \
|
||||
) \
|
||||
/**/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// debug flags for the pp-iterator library, possible flags (defined in
|
||||
// wave_config.hpp):
|
||||
//
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR 0x0001
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_TIME_CONVERSION 0x0002
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR 0x0004
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_INTLIT_GRAMMAR 0x0008
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR 0x0010
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_DEFINED_GRAMMAR 0x0020
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_PREDEF_MACROS_GRAMMAR 0x0040
|
||||
|
||||
#define BOOST_SPIRIT_DEBUG_FLAGS_CPP (\
|
||||
/* insert the required flags from above */ \
|
||||
) \
|
||||
/**/
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// For all recognized preprocessor statements the output parse trees
|
||||
// formatted as xml are printed. The formatted parse trees are streamed to the
|
||||
// std::ostream defined by the WAVE_DUMP_PARSE_TREE_OUT constant.
|
||||
//
|
||||
// Uncomment the following, if you want to see these parse trees.
|
||||
//
|
||||
//#define BOOST_WAVE_DUMP_PARSE_TREE 1
|
||||
//#define BOOST_WAVE_DUMP_PARSE_TREE_OUT std::cerr
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// For all #if and #elif directives the preprocessed expressions are printed.
|
||||
// These expressions are streamed to the std::ostream defined by the
|
||||
// WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT constant.
|
||||
//
|
||||
// Uncomment the following, if you want to see the preprocessed expressions
|
||||
//
|
||||
//#define BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS 1
|
||||
//#define BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT std::cerr
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to use the separate compilation model for the instantiation
|
||||
// of the C++ lexer objects.
|
||||
//
|
||||
// If this is defined, you should explicitly instantiate the C++ lexer
|
||||
// template with the correct parameters in a separate compilation unit of
|
||||
// your program (see the files instantiate_slex_lexer.cpp and
|
||||
// instantiate_re2c_lexer.cpp).
|
||||
//
|
||||
// To use the lexer inclusion model, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to use the separate compilation model for the instantiation
|
||||
// of the grammar objects.
|
||||
//
|
||||
// If this is defined, you should explicitly instantiate the grammar
|
||||
// templates with the correct parameters in a separate compilation unit of
|
||||
// your program (see the files instantiate_cpp_grammar.cpp).
|
||||
//
|
||||
// To use the grammar inclusion model, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MSVC specific #pragma's
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning (disable: 4355) // 'this' used in base member initializer list
|
||||
#pragma warning (disable: 4800) // forcing value to bool 'true' or 'false'
|
||||
#pragma inline_depth(255)
|
||||
#pragma inline_recursion(on)
|
||||
#endif // defined(BOOST_MSVC)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Now include the cofiguration stuff for the Wave library itself
|
||||
#include <boost/wave/wave_config.hpp>
|
||||
|
||||
#endif // !defined(CPP_TOKENS_HPP_7C0F1F14_6ACA_4439_A073_32C61C0DB6C5_INCLUDED)
|
||||
45
samples/cpp_tokens/instantiate_cpp_exprgrammar.cpp
Normal file
45
samples/cpp_tokens/instantiate_cpp_exprgrammar.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: prints out the preprocessed tokens returned by the pp iterator
|
||||
Explicit instantiation of the cpp_expression_grammar parsing
|
||||
function
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
|
||||
See Copyright.txt for full acknowledgements.
|
||||
=============================================================================*/
|
||||
|
||||
#include "cpp_tokens.hpp" // config data
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
|
||||
#include "slex_token.hpp"
|
||||
#include "slex_iterator.hpp"
|
||||
|
||||
#include <boost/wave/grammars/cpp_expression_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Explicit instantiation of the expression_grammar_gen template with the
|
||||
// correct token type. This instantiates the corresponding parse function,
|
||||
// which in turn instantiates the expression_grammar object (see
|
||||
// wave/grammars/cpp_expression_grammar.hpp)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boost::wave::cpp_token_sample::slex_token<> token_t;
|
||||
|
||||
template struct boost::wave::grammars::expression_grammar_gen<token_t>;
|
||||
|
||||
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
45
samples/cpp_tokens/instantiate_cpp_grammar.cpp
Normal file
45
samples/cpp_tokens/instantiate_cpp_grammar.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: prints out the preprocessed tokens returned by the pp iterator
|
||||
Explicit instantiation of the cpp_grammar parsing function
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
|
||||
See Copyright.txt for full acknowledgements.
|
||||
=============================================================================*/
|
||||
|
||||
#include "cpp_tokens.hpp" // config data
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
|
||||
#include "slex_token.hpp"
|
||||
#include "slex_iterator.hpp"
|
||||
|
||||
#include <boost/wave/grammars/cpp_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Explicit instantiation of the cpp_grammar_gen template with the correct
|
||||
// token type. This instantiates the corresponding pt_parse function, which
|
||||
// in turn instantiates the cpp_grammar object
|
||||
// (see wave/grammars/cpp_grammar.hpp)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boost::wave::cpp_token_sample::slex_iterator<
|
||||
boost::wave::cpp_token_sample::slex_token<> >
|
||||
lex_t;
|
||||
template struct boost::wave::grammars::cpp_grammar_gen<lex_t>;
|
||||
|
||||
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
46
samples/cpp_tokens/instantiate_cpp_literalgrammars.cpp
Normal file
46
samples/cpp_tokens/instantiate_cpp_literalgrammars.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: prints out the preprocessed tokens returned by the pp iterator
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
|
||||
See Copyright.txt for full acknowledgements.
|
||||
=============================================================================*/
|
||||
|
||||
#include "cpp_tokens.hpp" // config data
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
|
||||
#include "slex_token.hpp"
|
||||
#include "slex_iterator.hpp"
|
||||
|
||||
#include <boost/wave/grammars/cpp_literal_grammar_gen.hpp>
|
||||
#include <boost/wave/grammars/cpp_intlit_grammar.hpp>
|
||||
#include <boost/wave/grammars/cpp_chlit_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Explicit instantiation of the intlit_grammar_gen, chlit_grammar_gen and
|
||||
// floatlit_grammar_gen templates with the correct token type. This
|
||||
// instantiates the corresponding parse function, which in turn instantiates
|
||||
// the corresponding parser object.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boost::wave::cpp_token_sample::slex_token<> token_t;
|
||||
|
||||
template struct boost::wave::grammars::intlit_grammar_gen<token_t>;
|
||||
template struct boost::wave::grammars::chlit_grammar_gen<token_t>;
|
||||
|
||||
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
40
samples/cpp_tokens/instantiate_defined_grammar.cpp
Normal file
40
samples/cpp_tokens/instantiate_defined_grammar.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "cpp_tokens.hpp" // config data
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
|
||||
#include "slex_token.hpp"
|
||||
#include "slex_iterator.hpp"
|
||||
|
||||
#include <boost/wave/grammars/cpp_defined_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Explicit instantiation of the defined_grammar_gen template
|
||||
// with the correct token type. This instantiates the corresponding parse
|
||||
// function, which in turn instantiates the defined_grammar
|
||||
// object (see wave/grammars/cpp_defined_grammar.hpp)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boost::wave::cpp_token_sample::slex_iterator<
|
||||
boost::wave::cpp_token_sample::slex_token<> >
|
||||
lex_t;
|
||||
template struct boost::wave::grammars::defined_grammar_gen<lex_t>;
|
||||
|
||||
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
48
samples/cpp_tokens/instantiate_slex_lexer.cpp
Normal file
48
samples/cpp_tokens/instantiate_slex_lexer.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: Print out the preprocessed tokens returned by the Wave iterator
|
||||
Explicit instantiation of the lex_functor generation function
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "cpp_tokens.hpp" // config data
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
|
||||
#include "slex_token.hpp"
|
||||
#include "slex_iterator.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The following file needs to be included only once throughout the whole
|
||||
// program.
|
||||
#include "slex/cpp_slex_lexer.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This instantiates the correct 'new_lexer' function, which generates the
|
||||
// C++ lexer used in this sample.
|
||||
//
|
||||
// This is moved into a separate compilation unit to decouple the compilation
|
||||
// of the C++ lexer from the compilation of the other modules, which helps to
|
||||
// reduce compilation time.
|
||||
//
|
||||
// The template parameter(s) supplied should be identical to the parameters
|
||||
// supplied while instantiating the context<> template.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template struct boost::wave::cpp_token_sample::new_lexer_gen<
|
||||
std::string::iterator>;
|
||||
|
||||
#endif // BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION != 0
|
||||
657
samples/cpp_tokens/slex/cpp_slex_lexer.hpp
Normal file
657
samples/cpp_tokens/slex/cpp_slex_lexer.hpp
Normal file
@@ -0,0 +1,657 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
SLex (Spirit Lex) based C++ lexer
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(SLEX_LEXER_HPP_5E8E1DF0_BB41_4938_B7E5_A4BB68222FF6_INCLUDED)
|
||||
#define SLEX_LEXER_HPP_5E8E1DF0_BB41_4938_B7E5_A4BB68222FF6_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
#include <iostream>
|
||||
#endif // defined(BOOST_SPIRIT_DEBUG)
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/spirit/core.hpp>
|
||||
|
||||
#include <boost/wave/wave_config.hpp>
|
||||
#include <boost/wave/language_support.hpp>
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/util/file_position.hpp>
|
||||
#include <boost/wave/util/time_conversion_helper.hpp>
|
||||
#include <boost/wave/cpplexer/validate_universal_char.hpp>
|
||||
|
||||
#include "../slex_interface.hpp"
|
||||
#include "../slex_token.hpp"
|
||||
#include "../slex_iterator.hpp"
|
||||
|
||||
#include "lexer.hpp" // "spirit/lexer.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace cpp_token_sample {
|
||||
namespace slex {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// encapsulation of the boost::spirit::slex based cpp lexer
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename IteratorT, typename PositionT>
|
||||
class lexer
|
||||
: public boost::spirit::lexer<
|
||||
boost::wave::util::position_iterator<IteratorT, PositionT> >
|
||||
{
|
||||
public:
|
||||
|
||||
typedef boost::wave::util::position_iterator<IteratorT, PositionT>
|
||||
iterator_t;
|
||||
typedef typename std::iterator_traits<IteratorT>::value_type char_t;
|
||||
typedef boost::spirit::lexer<iterator_t> base_t;
|
||||
|
||||
typedef boost::wave::cpp_token_sample::slex_token<PositionT> token_t;
|
||||
|
||||
lexer();
|
||||
void init_dfa(boost::wave::language_support language);
|
||||
|
||||
// get time of last compilation
|
||||
static std::time_t get_compilation_time()
|
||||
{ return compilation_time.get_time(); }
|
||||
|
||||
private:
|
||||
// initialization data (regular expressions for the token definitions)
|
||||
struct lexer_data {
|
||||
token_id tokenid; // token data
|
||||
char_t const *tokenregex; // associated token to match
|
||||
typename base_t::callback_t tokencb; // associated callback function
|
||||
unsigned int lexerstate; // valid for lexer state
|
||||
};
|
||||
|
||||
static lexer_data const init_data[]; // common patterns
|
||||
static lexer_data const init_data_cpp[]; // C++ only patterns
|
||||
#if BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
static lexer_data const init_data_cpp0x[]; // C++0x only patterns
|
||||
#endif // BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
|
||||
// helper for calculation of the time of last compilation
|
||||
static boost::wave::util::time_conversion_helper compilation_time;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// data required for initialization of the lexer (token definitions)
|
||||
#define OR "|"
|
||||
#define Q(c) "\\" c
|
||||
#define TRI(c) Q("?") Q("?") c
|
||||
|
||||
// definition of some subtoken regexps to simplify the regex definitions
|
||||
#define BLANK "[ \\t]"
|
||||
#define CCOMMENT \
|
||||
Q("/") Q("*") "[^*]*" Q("*") "+" "(" "[^/*][^*]*" Q("*") "+" ")*" Q("/")
|
||||
|
||||
#define PPSPACE "(" BLANK OR CCOMMENT ")*"
|
||||
|
||||
#define OCTALDIGIT "[0-7]"
|
||||
#define DIGIT "[0-9]"
|
||||
#define HEXDIGIT "[0-9a-fA-F]"
|
||||
#define SIGN "[-+]?"
|
||||
#define EXPONENT "(" "[eE]" SIGN "[0-9]+" ")"
|
||||
|
||||
#define INTEGER_SUFFIX "(" "[uU][lL]?|[lL][uU]?" ")"
|
||||
#define FLOAT_SUFFIX "(" "[fF][lL]?|[lL][fF]?" ")"
|
||||
#define CHAR_SPEC "L?"
|
||||
|
||||
#define BACKSLASH "(" Q("\\") OR TRI(Q("/")) ")"
|
||||
#define ESCAPESEQ BACKSLASH "(" \
|
||||
"[abfnrtv?'\"]" OR \
|
||||
BACKSLASH OR \
|
||||
"x" HEXDIGIT "+" OR \
|
||||
OCTALDIGIT OCTALDIGIT "?" OCTALDIGIT "?" \
|
||||
")"
|
||||
#define HEXQUAD HEXDIGIT HEXDIGIT HEXDIGIT HEXDIGIT
|
||||
#define UNIVERSALCHAR BACKSLASH "(" \
|
||||
"u" HEXQUAD OR \
|
||||
"U" HEXQUAD HEXQUAD \
|
||||
")"
|
||||
|
||||
#define POUNDDEF "(" "#" OR TRI("=") OR Q("%:") ")"
|
||||
#define NEWLINEDEF "(" "\\n" OR "\\r" OR "\\r\\n" ")"
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
|
||||
#define INCLUDEDEF "(include|include_next)"
|
||||
#else
|
||||
#define INCLUDEDEF "include"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// sexer state constants
|
||||
#define LEXER_STATE_NORMAL 0
|
||||
#define LEXER_STATE_PP 1
|
||||
|
||||
#define NUM_LEXER_STATES 1
|
||||
|
||||
// helper for initializing token data
|
||||
#define TOKEN_DATA(id, regex) \
|
||||
{ T_##id, regex, 0, LEXER_STATE_NORMAL }
|
||||
|
||||
#define TOKEN_DATA_EX(id, regex, callback) \
|
||||
{ T_##id, regex, callback, LEXER_STATE_NORMAL }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// common C++/C99 token definitions
|
||||
template <typename IteratorT, typename PositionT>
|
||||
typename lexer<IteratorT, PositionT>::lexer_data const
|
||||
lexer<IteratorT, PositionT>::init_data[] =
|
||||
{
|
||||
TOKEN_DATA(AND, "&"),
|
||||
TOKEN_DATA(ANDAND, "&&"),
|
||||
TOKEN_DATA(ASSIGN, "="),
|
||||
TOKEN_DATA(ANDASSIGN, "&="),
|
||||
TOKEN_DATA(OR, Q("|")),
|
||||
TOKEN_DATA(OR_TRIGRAPH, TRI("!")),
|
||||
TOKEN_DATA(ORASSIGN, Q("|=") OR TRI("!=")),
|
||||
TOKEN_DATA(XOR, Q("^")),
|
||||
TOKEN_DATA(XOR_TRIGRAPH, TRI("'")),
|
||||
TOKEN_DATA(XORASSIGN, Q("^=") OR TRI("'=")),
|
||||
TOKEN_DATA(COMMA, ","),
|
||||
TOKEN_DATA(COLON, ":"),
|
||||
TOKEN_DATA(DIVIDE, Q("/")),
|
||||
TOKEN_DATA(DIVIDEASSIGN, Q("/=")),
|
||||
TOKEN_DATA(DOT, Q(".")),
|
||||
TOKEN_DATA(ELLIPSIS, Q(".") Q(".") Q(".")),
|
||||
TOKEN_DATA(EQUAL, "=="),
|
||||
TOKEN_DATA(GREATER, ">"),
|
||||
TOKEN_DATA(GREATEREQUAL, ">="),
|
||||
TOKEN_DATA(LEFTBRACE, Q("{")),
|
||||
TOKEN_DATA(LEFTBRACE_ALT, "<" Q("%")),
|
||||
TOKEN_DATA(LEFTBRACE_TRIGRAPH, TRI("<")),
|
||||
TOKEN_DATA(LESS, "<"),
|
||||
TOKEN_DATA(LESSEQUAL, "<="),
|
||||
TOKEN_DATA(LEFTPAREN, Q("(")),
|
||||
TOKEN_DATA(LEFTBRACKET, Q("[")),
|
||||
TOKEN_DATA(LEFTBRACKET_ALT, "<:"),
|
||||
TOKEN_DATA(LEFTBRACKET_TRIGRAPH, TRI(Q("("))),
|
||||
TOKEN_DATA(MINUS, Q("-")),
|
||||
TOKEN_DATA(MINUSASSIGN, Q("-=")),
|
||||
TOKEN_DATA(MINUSMINUS, Q("-") Q("-")),
|
||||
TOKEN_DATA(PERCENT, Q("%")),
|
||||
TOKEN_DATA(PERCENTASSIGN, Q("%=")),
|
||||
TOKEN_DATA(NOT, "!"),
|
||||
TOKEN_DATA(NOTEQUAL, "!="),
|
||||
TOKEN_DATA(OROR, Q("|") Q("|") OR TRI("!") Q("|") OR Q("|") TRI("!") OR
|
||||
TRI("!") TRI("!")),
|
||||
TOKEN_DATA(PLUS, Q("+")),
|
||||
TOKEN_DATA(PLUSASSIGN, Q("+=")),
|
||||
TOKEN_DATA(PLUSPLUS, Q("+") Q("+")),
|
||||
TOKEN_DATA(ARROW, Q("->")),
|
||||
TOKEN_DATA(QUESTION_MARK, Q("?")),
|
||||
TOKEN_DATA(RIGHTBRACE, Q("}")),
|
||||
TOKEN_DATA(RIGHTBRACE_ALT, Q("%>")),
|
||||
TOKEN_DATA(RIGHTBRACE_TRIGRAPH, TRI(">")),
|
||||
TOKEN_DATA(RIGHTPAREN, Q(")")),
|
||||
TOKEN_DATA(RIGHTBRACKET, Q("]")),
|
||||
TOKEN_DATA(RIGHTBRACKET_ALT, ":>"),
|
||||
TOKEN_DATA(RIGHTBRACKET_TRIGRAPH, TRI(Q(")"))),
|
||||
TOKEN_DATA(SEMICOLON, ";"),
|
||||
TOKEN_DATA(SHIFTLEFT, "<<"),
|
||||
TOKEN_DATA(SHIFTLEFTASSIGN, "<<="),
|
||||
TOKEN_DATA(SHIFTRIGHT, ">>"),
|
||||
TOKEN_DATA(SHIFTRIGHTASSIGN, ">>="),
|
||||
TOKEN_DATA(STAR, Q("*")),
|
||||
TOKEN_DATA(COMPL, Q("~")),
|
||||
TOKEN_DATA(COMPL_TRIGRAPH, TRI("-")),
|
||||
TOKEN_DATA(STARASSIGN, Q("*=")),
|
||||
TOKEN_DATA(ASM, "asm"),
|
||||
TOKEN_DATA(AUTO, "auto"),
|
||||
TOKEN_DATA(BOOL, "bool"),
|
||||
TOKEN_DATA(FALSE, "false"),
|
||||
TOKEN_DATA(TRUE, "true"),
|
||||
TOKEN_DATA(BREAK, "break"),
|
||||
TOKEN_DATA(CASE, "case"),
|
||||
TOKEN_DATA(CATCH, "catch"),
|
||||
TOKEN_DATA(CHAR, "char"),
|
||||
TOKEN_DATA(CLASS, "class"),
|
||||
TOKEN_DATA(CONST, "const"),
|
||||
TOKEN_DATA(CONSTCAST, "const_cast"),
|
||||
TOKEN_DATA(CONTINUE, "continue"),
|
||||
TOKEN_DATA(DEFAULT, "default"),
|
||||
// TOKEN_DATA(DEFINED, "defined"),
|
||||
TOKEN_DATA(DELETE, "delete"),
|
||||
TOKEN_DATA(DO, "do"),
|
||||
TOKEN_DATA(DOUBLE, "double"),
|
||||
TOKEN_DATA(DYNAMICCAST, "dynamic_cast"),
|
||||
TOKEN_DATA(ELSE, "else"),
|
||||
TOKEN_DATA(ENUM, "enum"),
|
||||
TOKEN_DATA(EXPLICIT, "explicit"),
|
||||
TOKEN_DATA(EXPORT, "export"),
|
||||
TOKEN_DATA(EXTERN, "extern"),
|
||||
TOKEN_DATA(FLOAT, "float"),
|
||||
TOKEN_DATA(FOR, "for"),
|
||||
TOKEN_DATA(FRIEND, "friend"),
|
||||
TOKEN_DATA(GOTO, "goto"),
|
||||
TOKEN_DATA(IF, "if"),
|
||||
TOKEN_DATA(INLINE, "inline"),
|
||||
TOKEN_DATA(INT, "int"),
|
||||
TOKEN_DATA(LONG, "long"),
|
||||
TOKEN_DATA(MUTABLE, "mutable"),
|
||||
TOKEN_DATA(NAMESPACE, "namespace"),
|
||||
TOKEN_DATA(NEW, "new"),
|
||||
TOKEN_DATA(OPERATOR, "operator"),
|
||||
TOKEN_DATA(PRIVATE, "private"),
|
||||
TOKEN_DATA(PROTECTED, "protected"),
|
||||
TOKEN_DATA(PUBLIC, "public"),
|
||||
TOKEN_DATA(REGISTER, "register"),
|
||||
TOKEN_DATA(REINTERPRETCAST, "reinterpret_cast"),
|
||||
TOKEN_DATA(RETURN, "return"),
|
||||
TOKEN_DATA(SHORT, "short"),
|
||||
TOKEN_DATA(SIGNED, "signed"),
|
||||
TOKEN_DATA(SIZEOF, "sizeof"),
|
||||
TOKEN_DATA(STATIC, "static"),
|
||||
TOKEN_DATA(STATICCAST, "static_cast"),
|
||||
TOKEN_DATA(STRUCT, "struct"),
|
||||
TOKEN_DATA(SWITCH, "switch"),
|
||||
TOKEN_DATA(TEMPLATE, "template"),
|
||||
TOKEN_DATA(THIS, "this"),
|
||||
TOKEN_DATA(THROW, "throw"),
|
||||
TOKEN_DATA(TRY, "try"),
|
||||
TOKEN_DATA(TYPEDEF, "typedef"),
|
||||
TOKEN_DATA(TYPEID, "typeid"),
|
||||
TOKEN_DATA(TYPENAME, "typename"),
|
||||
TOKEN_DATA(UNION, "union"),
|
||||
TOKEN_DATA(UNSIGNED, "unsigned"),
|
||||
TOKEN_DATA(USING, "using"),
|
||||
TOKEN_DATA(VIRTUAL, "virtual"),
|
||||
TOKEN_DATA(VOID, "void"),
|
||||
TOKEN_DATA(VOLATILE, "volatile"),
|
||||
TOKEN_DATA(WCHART, "wchar_t"),
|
||||
TOKEN_DATA(WHILE, "while"),
|
||||
TOKEN_DATA(PP_DEFINE, POUNDDEF PPSPACE "define"),
|
||||
TOKEN_DATA(PP_IF, POUNDDEF PPSPACE "if"),
|
||||
TOKEN_DATA(PP_IFDEF, POUNDDEF PPSPACE "ifdef"),
|
||||
TOKEN_DATA(PP_IFNDEF, POUNDDEF PPSPACE "ifndef"),
|
||||
TOKEN_DATA(PP_ELSE, POUNDDEF PPSPACE "else"),
|
||||
TOKEN_DATA(PP_ELIF, POUNDDEF PPSPACE "elif"),
|
||||
TOKEN_DATA(PP_ENDIF, POUNDDEF PPSPACE "endif"),
|
||||
TOKEN_DATA(PP_ERROR, POUNDDEF PPSPACE "error"),
|
||||
TOKEN_DATA(PP_QHEADER, POUNDDEF PPSPACE \
|
||||
INCLUDEDEF PPSPACE Q("\"") "[^\\n\\r\"]+" Q("\"")),
|
||||
TOKEN_DATA(PP_HHEADER, POUNDDEF PPSPACE \
|
||||
INCLUDEDEF PPSPACE "<" "[^\\n\\r>]+" ">"),
|
||||
TOKEN_DATA(PP_INCLUDE, POUNDDEF PPSPACE \
|
||||
INCLUDEDEF PPSPACE),
|
||||
TOKEN_DATA(PP_LINE, POUNDDEF PPSPACE "line"),
|
||||
TOKEN_DATA(PP_PRAGMA, POUNDDEF PPSPACE "pragma"),
|
||||
TOKEN_DATA(PP_UNDEF, POUNDDEF PPSPACE "undef"),
|
||||
TOKEN_DATA(PP_WARNING, POUNDDEF PPSPACE "warning"),
|
||||
TOKEN_DATA(IDENTIFIER, "([a-zA-Z_]" OR UNIVERSALCHAR ")([a-zA-Z0-9_]" OR UNIVERSALCHAR ")*"),
|
||||
// TOKEN_DATA(OCTALINT, "0" OCTALDIGIT "*" INTEGER_SUFFIX "?"),
|
||||
// TOKEN_DATA(DECIMALINT, "[1-9]" DIGIT "*" INTEGER_SUFFIX "?"),
|
||||
// TOKEN_DATA(HEXAINT, "(0x|0X)" HEXDIGIT "+" INTEGER_SUFFIX "?"),
|
||||
TOKEN_DATA(INTLIT, "(" "(0x|0X)" HEXDIGIT "+" OR "0" OCTALDIGIT "*" OR \
|
||||
"[1-9]" DIGIT "*" ")" INTEGER_SUFFIX "?"),
|
||||
TOKEN_DATA(FLOATLIT,
|
||||
"(" DIGIT "*" Q(".") DIGIT "+" OR DIGIT "+" Q(".") ")"
|
||||
EXPONENT "?" FLOAT_SUFFIX "?" OR
|
||||
DIGIT "+" EXPONENT FLOAT_SUFFIX "?"),
|
||||
TOKEN_DATA(CCOMMENT, CCOMMENT),
|
||||
TOKEN_DATA(CPPCOMMENT, Q("/") Q("/[^\\n\\r]*") NEWLINEDEF ),
|
||||
TOKEN_DATA(CHARLIT, CHAR_SPEC "'"
|
||||
"(" ESCAPESEQ OR "[^\\n\\r']" OR UNIVERSALCHAR ")+" "'"),
|
||||
TOKEN_DATA(STRINGLIT, CHAR_SPEC Q("\"")
|
||||
"(" ESCAPESEQ OR "[^\\n\\r\"]" OR UNIVERSALCHAR ")*" Q("\"")),
|
||||
TOKEN_DATA(SPACE, BLANK "+"),
|
||||
TOKEN_DATA(SPACE2, "[\\v\\f]+"),
|
||||
TOKEN_DATA(CONTLINE, Q("\\") "\\n"),
|
||||
TOKEN_DATA(NEWLINE, NEWLINEDEF),
|
||||
TOKEN_DATA(POUND_POUND, "##"),
|
||||
TOKEN_DATA(POUND_POUND_ALT, Q("%:") Q("%:")),
|
||||
TOKEN_DATA(POUND_POUND_TRIGRAPH, TRI("=") TRI("=")),
|
||||
TOKEN_DATA(POUND, "#"),
|
||||
TOKEN_DATA(POUND_ALT, Q("%:")),
|
||||
TOKEN_DATA(POUND_TRIGRAPH, TRI("=")),
|
||||
TOKEN_DATA(ANY, "."),
|
||||
#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
|
||||
TOKEN_DATA(MSEXT_INT8, "__int8"),
|
||||
TOKEN_DATA(MSEXT_INT16, "__int16"),
|
||||
TOKEN_DATA(MSEXT_INT32, "__int32"),
|
||||
TOKEN_DATA(MSEXT_INT64, "__int64"),
|
||||
TOKEN_DATA(MSEXT_BASED, "_?" "_based"),
|
||||
TOKEN_DATA(MSEXT_DECLSPEC, "_?" "_declspec"),
|
||||
TOKEN_DATA(MSEXT_CDECL, "_?" "_cdecl"),
|
||||
TOKEN_DATA(MSEXT_FASTCALL, "_?" "_fastcall"),
|
||||
TOKEN_DATA(MSEXT_STDCALL, "_?" "_stdcall"),
|
||||
TOKEN_DATA(MSEXT_TRY , "__try"),
|
||||
TOKEN_DATA(MSEXT_EXCEPT, "__except"),
|
||||
TOKEN_DATA(MSEXT_FINALLY, "__finally"),
|
||||
TOKEN_DATA(MSEXT_LEAVE, "__leave"),
|
||||
TOKEN_DATA(MSEXT_INLINE, "_?" "_inline"),
|
||||
TOKEN_DATA(MSEXT_ASM, "_?" "_asm"),
|
||||
#endif // BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
|
||||
#if BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
TOKEN_DATA(PP_REGION, POUNDDEF PPSPACE BOOST_WAVE_PP_REGION),
|
||||
TOKEN_DATA(PP_ENDREGION, POUNDDEF PPSPACE BOOST_WAVE_PP_ENDREGION),
|
||||
TOKEN_DATA(PP_IMPORT, POUNDDEF PPSPACE BOOST_WAVE_PP_IMPORT),
|
||||
#endif // BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
{ token_id(0) } // this should be the last entry
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// C++ only token definitions
|
||||
template <typename IteratorT, typename PositionT>
|
||||
typename lexer<IteratorT, PositionT>::lexer_data const
|
||||
lexer<IteratorT, PositionT>::init_data_cpp[] =
|
||||
{
|
||||
TOKEN_DATA(AND_ALT, "bitand"),
|
||||
TOKEN_DATA(ANDAND_ALT, "and"),
|
||||
TOKEN_DATA(ANDASSIGN_ALT, "and_eq"),
|
||||
TOKEN_DATA(OR_ALT, "bitor"),
|
||||
TOKEN_DATA(ORASSIGN_ALT, "or_eq"),
|
||||
TOKEN_DATA(OROR_ALT, "or"),
|
||||
TOKEN_DATA(XOR_ALT, "xor"),
|
||||
TOKEN_DATA(XORASSIGN_ALT, "xor_eq"),
|
||||
TOKEN_DATA(NOT_ALT, "not"),
|
||||
TOKEN_DATA(NOTEQUAL_ALT, "not_eq"),
|
||||
TOKEN_DATA(COMPL_ALT, "compl"),
|
||||
TOKEN_DATA(ARROWSTAR, Q("->") Q("*")),
|
||||
TOKEN_DATA(DOTSTAR, Q(".") Q("*")),
|
||||
TOKEN_DATA(COLON_COLON, "::"),
|
||||
{ token_id(0) } // this should be the last entry
|
||||
};
|
||||
|
||||
#if BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// C++0x only token definitions
|
||||
template <typename IteratorT, typename PositionT>
|
||||
typename lexer<IteratorT, PositionT>::lexer_data const
|
||||
lexer<IteratorT, PositionT>::init_data_cpp0x[] =
|
||||
{
|
||||
TOKEN_DATA(COMMA_ALT, "__comma__"),
|
||||
TOKEN_DATA(LEFTPAREN_ALT, "__lparen__"),
|
||||
TOKEN_DATA(RIGHTPAREN_ALT, "__rparen__"),
|
||||
{ token_id(0) } // this should be the last entry
|
||||
};
|
||||
#endif // BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// undefine macros, required for regular expression definitions
|
||||
#undef INCLUDEDEF
|
||||
#undef POUNDDEF
|
||||
#undef CCOMMENT
|
||||
#undef PPSPACE
|
||||
#undef DIGIT
|
||||
#undef OCTALDIGIT
|
||||
#undef HEXDIGIT
|
||||
#undef SIGN
|
||||
#undef EXPONENT
|
||||
#undef INTEGER_SUFFIX
|
||||
#undef FLOAT_SUFFIX
|
||||
#undef CHAR_SPEC
|
||||
#undef BACKSLASH
|
||||
#undef ESCAPESEQ
|
||||
#undef HEXQUAD
|
||||
#undef UNIVERSALCHAR
|
||||
|
||||
#undef Q
|
||||
#undef TRI
|
||||
#undef OR
|
||||
|
||||
#undef TOKEN_DATA
|
||||
#undef TOKEN_DATA_EX
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// initialize cpp lexer with token data
|
||||
template <typename IteratorT, typename PositionT>
|
||||
inline
|
||||
lexer<IteratorT, PositionT>::lexer()
|
||||
: base_t(NUM_LEXER_STATES)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename IteratorT, typename PositionT>
|
||||
inline void
|
||||
lexer<IteratorT, PositionT>::init_dfa(boost::wave::language_support lang)
|
||||
{
|
||||
// the modes are mutually exclusive
|
||||
#if BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
BOOST_ASSERT(!boost::wave::need_c99(lang) || !boost::wave::need_cpp0x(lang));
|
||||
#endif // BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
|
||||
if (has_compiled_dfa())
|
||||
return;
|
||||
|
||||
for (int i = 0; 0 != init_data[i].tokenid; ++i) {
|
||||
this->register_regex(init_data[i].tokenregex, init_data[i].tokenid,
|
||||
init_data[i].tokencb, init_data[i].lexerstate);
|
||||
}
|
||||
|
||||
// if in C99 mode, some of the keywords are not valid
|
||||
if (!boost::wave::need_c99(lang)) {
|
||||
for (int j = 0; 0 != init_data_cpp[j].tokenid; ++j) {
|
||||
this->register_regex(init_data_cpp[j].tokenregex,
|
||||
init_data_cpp[j].tokenid, init_data_cpp[j].tokencb,
|
||||
init_data_cpp[j].lexerstate);
|
||||
}
|
||||
}
|
||||
|
||||
#if BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
// C++0x mode has it's own new keywords
|
||||
if (boost::wave::need_cpp0x(lang)) {
|
||||
for (int k = 0; 0 != init_data_cpp0x[k].tokenid; ++k) {
|
||||
this->register_regex(init_data_cpp0x[k].tokenregex,
|
||||
init_data_cpp0x[k].tokenid, init_data_cpp0x[k].tokencb,
|
||||
init_data_cpp0x[k].lexerstate);
|
||||
}
|
||||
}
|
||||
#endif // BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS != 0
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// get time of last compilation of this file
|
||||
template <typename IteratorT, typename PositionT>
|
||||
boost::wave::util::time_conversion_helper
|
||||
lexer<IteratorT, PositionT>::compilation_time(__DATE__ " " __TIME__);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
template <typename IteratorT, typename PositionT>
|
||||
inline void
|
||||
init_lexer (lexer<IteratorT, PositionT> &lexer,
|
||||
boost::wave::language_support language, bool force_reinit = false)
|
||||
{
|
||||
if (lexer.has_compiled_dfa())
|
||||
return; // nothing to do
|
||||
|
||||
using std::ifstream;
|
||||
using std::ofstream;
|
||||
using std::ios;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
ifstream dfa_in("wave_slex_lexer.dfa", ios::in|ios::binary);
|
||||
|
||||
lexer.init_dfa(language);
|
||||
if (force_reinit || !dfa_in.is_open() ||
|
||||
!lexer.load (dfa_in, (long)lexer.get_compilation_time()))
|
||||
{
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
cerr << "Compiling regular expressions for slex ...";
|
||||
#endif // defined(BOOST_SPIRIT_DEBUG)
|
||||
|
||||
dfa_in.close();
|
||||
lexer.create_dfa();
|
||||
|
||||
ofstream dfa_out ("wave_slex_lexer.dfa", ios::out|ios::binary|ios::trunc);
|
||||
|
||||
if (dfa_out.is_open())
|
||||
lexer.save (dfa_out, (long)lexer.get_compilation_time());
|
||||
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
cerr << " Done." << endl;
|
||||
#endif // defined(BOOST_SPIRIT_DEBUG)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lex_functor
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename IteratorT, typename PositionT = wave::util::file_position_t>
|
||||
class slex_functor
|
||||
: public slex_input_interface<typename lexer<IteratorT, PositionT>::token_t>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef boost::wave::util::position_iterator<IteratorT, PositionT>
|
||||
iterator_t;
|
||||
typedef typename std::iterator_traits<IteratorT>::value_type char_t;
|
||||
typedef BOOST_WAVE_STRINGTYPE string_t;
|
||||
typedef typename lexer<IteratorT, PositionT>::token_t token_t;
|
||||
|
||||
slex_functor(IteratorT const &first_, IteratorT const &last_,
|
||||
PositionT const &pos_, boost::wave::language_support language)
|
||||
: first(first_, last_, pos_), at_eof(false)
|
||||
{
|
||||
// initialize lexer dfa tables
|
||||
init_lexer(lexer, language);
|
||||
}
|
||||
virtual ~slex_functor() {}
|
||||
|
||||
// get the next token from the input stream
|
||||
token_t get()
|
||||
{
|
||||
token_t token;
|
||||
|
||||
if (!at_eof) {
|
||||
do {
|
||||
// generate and return the next token
|
||||
std::string value;
|
||||
PositionT const &pos = first.get_position();
|
||||
token_id id = token_id(lexer.next_token(first, last, &value));
|
||||
|
||||
if ((token_id)(-1) == id)
|
||||
id = T_EOF; // end of input reached
|
||||
|
||||
string_t token_val(value.c_str());
|
||||
|
||||
if (T_CONTLINE != id) {
|
||||
switch (id) {
|
||||
case T_IDENTIFIER:
|
||||
// test identifier characters for validity (throws if
|
||||
// invalid chars found)
|
||||
using boost::wave::cpplexer::impl::validate_identifier_name;
|
||||
validate_identifier_name(token_val,
|
||||
pos.get_line(), pos.get_column(), pos.get_file());
|
||||
break;
|
||||
|
||||
case T_STRINGLIT:
|
||||
case T_CHARLIT:
|
||||
// test literal characters for validity (throws if invalid
|
||||
// chars found)
|
||||
using boost::wave::cpplexer::impl::validate_literal;
|
||||
validate_literal(token_val,
|
||||
pos.get_line(), pos.get_column(), pos.get_file());
|
||||
break;
|
||||
|
||||
#if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
|
||||
case T_PP_HHEADER:
|
||||
case T_PP_QHEADER:
|
||||
case T_PP_INCLUDE:
|
||||
// convert to the corresponding ..._next token, if appropriate
|
||||
if (string_t::npos != value.find("include_"))
|
||||
id = token_id(id | AltTokenType);
|
||||
break;
|
||||
#endif // BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
|
||||
|
||||
case T_EOF:
|
||||
// T_EOF is returned as a valid token, the next call will
|
||||
// return T_EOI, i.e. the actual end of input
|
||||
at_eof = true;
|
||||
break;
|
||||
}
|
||||
return token_t(id, token_val, pos);
|
||||
}
|
||||
|
||||
// skip the T_CONTLINE token
|
||||
} while (true);
|
||||
}
|
||||
return token; // return T_EOI
|
||||
}
|
||||
void set_position(PositionT const &pos)
|
||||
{ first.set_position(pos); }
|
||||
|
||||
private:
|
||||
iterator_t first;
|
||||
iterator_t last;
|
||||
static lexer<IteratorT, PositionT> lexer; // needed only once
|
||||
|
||||
bool at_eof;
|
||||
};
|
||||
|
||||
template <typename IteratorT, typename PositionT>
|
||||
lexer<IteratorT, PositionT> slex_functor<IteratorT, PositionT>::lexer;
|
||||
|
||||
} // namespace slex
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The 'new_lexer' function allows the opaque generation of a new lexer object.
|
||||
// It is coupled to the iterator type to allow to decouple the lexer/iterator
|
||||
// configurations at compile time.
|
||||
//
|
||||
// This function is declared inside the cpp_slex_token.hpp file, which is
|
||||
// referenced by the source file calling the lexer and the source file, which
|
||||
// instantiates the lex_functor. But is is defined here, so it will be
|
||||
// instantiated only while compiling the source file, which instantiates the
|
||||
// lex_functor. While the cpp_slex_token.hpp file may be included everywhere,
|
||||
// this file (cpp_slex_lexer.hpp) should be included only once. This allows
|
||||
// to decouple the lexer interface from the lexer implementation and reduces
|
||||
// compilation time.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The new_lexer_gen<>::new_lexer function (declared in cpp_slex_token.hpp)
|
||||
// should be defined inline, if the lex_functor shouldn't be instantiated
|
||||
// separately from the lex_iterator.
|
||||
//
|
||||
// Separate (explicit) instantiation helps to reduce compilation time.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION != 0
|
||||
#define BOOST_WAVE_SLEX_NEW_LEXER_INLINE
|
||||
#else
|
||||
#define BOOST_WAVE_SLEX_NEW_LEXER_INLINE inline
|
||||
#endif
|
||||
|
||||
template <typename IteratorT, typename PositionT>
|
||||
BOOST_WAVE_SLEX_NEW_LEXER_INLINE
|
||||
slex_input_interface<slex_token<PositionT> > *
|
||||
new_lexer_gen<IteratorT, PositionT>::new_lexer(IteratorT const &first,
|
||||
IteratorT const &last, PositionT const &pos,
|
||||
boost::wave::language_support language)
|
||||
{
|
||||
return new slex::slex_functor<IteratorT, PositionT>(first, last, pos,
|
||||
language);
|
||||
}
|
||||
|
||||
#undef BOOST_WAVE_SLEX_NEW_LEXER_INLINE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace cpp_token_sample
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(SLEX_LEXER_HPP_5E8E1DF0_BB41_4938_B7E5_A4BB68222FF6_INCLUDED)
|
||||
2894
samples/cpp_tokens/slex/lexer.hpp
Normal file
2894
samples/cpp_tokens/slex/lexer.hpp
Normal file
File diff suppressed because it is too large
Load Diff
82
samples/cpp_tokens/slex_interface.hpp
Normal file
82
samples/cpp_tokens/slex_interface.hpp
Normal file
@@ -0,0 +1,82 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Definition of the abstract lexer interface
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(SLEX_INTERFACE_HPP_E83F52A4_90AC_4FBE_A9A7_B65F7F94C497_INCLUDED)
|
||||
#define SLEX_INTERFACE_HPP_E83F52A4_90AC_4FBE_A9A7_B65F7F94C497_INCLUDED
|
||||
|
||||
#include <boost/wave/language_support.hpp>
|
||||
#include <boost/wave/util/file_position.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace cpp_token_sample {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// new_lexer_gen: generates a new instance of the required C++ lexer
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename TokenT> struct slex_input_interface;
|
||||
|
||||
template <
|
||||
typename IteratorT,
|
||||
typename PositionT = boost::wave::util::file_position_t
|
||||
>
|
||||
struct new_lexer_gen
|
||||
{
|
||||
// The NewLexer function allows the opaque generation of a new lexer object.
|
||||
// It is coupled to the token type to allow to decouple the lexer/token
|
||||
// configurations at compile time.
|
||||
static slex_input_interface<slex_token<PositionT> > *
|
||||
new_lexer(IteratorT const &first, IteratorT const &last,
|
||||
PositionT const &pos, boost::wave::language_support language);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The lex_input_interface decouples the lex_iterator_shim from the actual
|
||||
// lexer. This is done to allow compile time reduction.
|
||||
// Thanks to JCAB for having this idea.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename TokenT>
|
||||
struct slex_input_interface
|
||||
{
|
||||
typedef typename TokenT::position_t position_t;
|
||||
|
||||
virtual TokenT get() = 0;
|
||||
virtual void set_position(position_t const &pos) = 0;
|
||||
|
||||
virtual ~slex_input_interface() {}
|
||||
|
||||
// The new_lexer function allows the opaque generation of a new lexer object.
|
||||
// It is coupled to the token type to allow to distinguish different
|
||||
// lexer/token configurations at compile time.
|
||||
template <typename IteratorT>
|
||||
static slex_input_interface *
|
||||
new_lexer(IteratorT const &first, IteratorT const &last,
|
||||
position_t const &pos, boost::wave::language_support language)
|
||||
{
|
||||
return new_lexer_gen<IteratorT, position_t>::new_lexer (first, last,
|
||||
pos, language);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace cpp_token_sample
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(SLEX_INTERFACE_HPP_E83F52A4_90AC_4FBE_A9A7_B65F7F94C497_INCLUDED)
|
||||
136
samples/cpp_tokens/slex_iterator.hpp
Normal file
136
samples/cpp_tokens/slex_iterator.hpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Definition of the lexer iterator
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED)
|
||||
#define SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/spirit/iterator/multi_pass.hpp>
|
||||
|
||||
#include <boost/wave/language_support.hpp>
|
||||
#include <boost/wave/util/file_position.hpp>
|
||||
#include <boost/wave/util/functor_input.hpp>
|
||||
|
||||
#include "slex_interface.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace cpp_token_sample {
|
||||
namespace impl {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lex_iterator_functor_shim
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename TokenT>
|
||||
class slex_iterator_functor_shim
|
||||
{
|
||||
public:
|
||||
template <typename IteratorT>
|
||||
slex_iterator_functor_shim(IteratorT const &first, IteratorT const &last,
|
||||
typename TokenT::position_t const &pos,
|
||||
boost::wave::language_support language)
|
||||
: functor_ptr(slex_input_interface<TokenT>
|
||||
::new_lexer(first, last, pos, language))
|
||||
{}
|
||||
|
||||
// interface to the boost::spirit::multi_pass_policies::functor_input policy
|
||||
typedef TokenT result_type;
|
||||
|
||||
/*static*/ result_type const eof;
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
BOOST_ASSERT(0 != functor_ptr.get());
|
||||
return functor_ptr->get();
|
||||
}
|
||||
void set_position(typename TokenT::position_t const &pos)
|
||||
{
|
||||
BOOST_ASSERT(0 != functor_ptr.get());
|
||||
functor_ptr->set_position(pos);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::shared_ptr<slex_input_interface<TokenT> > functor_ptr;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// eof token
|
||||
//template <typename TokenT>
|
||||
//typename slex_iterator_functor_shim<TokenT>::result_type const
|
||||
// slex_iterator_functor_shim<TokenT>::eof =
|
||||
// typename slex_iterator_functor_shim<TokenT>::result_type();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace impl
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// slex_iterator
|
||||
//
|
||||
// A generic C++ lexer interface class, which allows to plug in different
|
||||
// lexer implementations (template parameter LexT). The following
|
||||
// requirement apply:
|
||||
//
|
||||
// - the lexer type should have a function implemented, which returnes
|
||||
// the next lexed token from the input stream:
|
||||
// typename LexT::token_t get();
|
||||
// - at the end of the input stream this function should return the
|
||||
// eof token equivalent
|
||||
// - the lexer should implement a constructor taking two iterators
|
||||
// pointing to the beginning and the end of the input stream and
|
||||
// a third parameter containing the name of the parsed input file
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename TokenT>
|
||||
class slex_iterator
|
||||
: public boost::spirit::multi_pass<
|
||||
impl::slex_iterator_functor_shim<TokenT>,
|
||||
boost::wave::util::functor_input
|
||||
>
|
||||
{
|
||||
typedef impl::slex_iterator_functor_shim<TokenT> input_policy_t;
|
||||
typedef
|
||||
boost::spirit::multi_pass<input_policy_t,
|
||||
boost::wave::util::functor_input>
|
||||
base_t;
|
||||
typedef slex_iterator<TokenT> self_t;
|
||||
|
||||
public:
|
||||
typedef TokenT token_t;
|
||||
|
||||
slex_iterator()
|
||||
{}
|
||||
|
||||
template <typename IteratorT>
|
||||
slex_iterator(IteratorT const &first, IteratorT const &last,
|
||||
typename TokenT::position_t const &pos,
|
||||
boost::wave::language_support language)
|
||||
: base_t(input_policy_t(first, last, pos, language))
|
||||
{}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace cpp_token_sample
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(SLEX_ITERATOR_HPP_AF0C37E3_CBD8_4F33_A225_51CF576FA61F_INCLUDED)
|
||||
116
samples/cpp_tokens/slex_token.hpp
Normal file
116
samples/cpp_tokens/slex_token.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
A generic C++ lexer token definition
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(SLEX_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED)
|
||||
#define SLEX_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include <boost/wave/wave_config.hpp>
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/language_support.hpp>
|
||||
#include <boost/wave/util/file_position.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace cpp_token_sample {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// forward declaration of the token type
|
||||
template <typename PositionT = boost::wave::util::file_position_t>
|
||||
class slex_token;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lex_token
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PositionT>
|
||||
class slex_token
|
||||
{
|
||||
public:
|
||||
typedef BOOST_WAVE_STRINGTYPE string_t;
|
||||
typedef PositionT position_t;
|
||||
|
||||
slex_token()
|
||||
: id(T_EOI)
|
||||
{}
|
||||
|
||||
slex_token(token_id id_, string_t const &value_, PositionT const &pos_)
|
||||
: id(id_), value(value_), pos(pos_)
|
||||
{}
|
||||
|
||||
// accessors
|
||||
operator token_id() const { return id; }
|
||||
string_t const &get_value() const { return value; }
|
||||
position_t const &get_position() const { return pos; }
|
||||
void set_token_id (token_id id_) { id = id_; }
|
||||
void set_value (string_t const &newval) { value = newval; }
|
||||
void set_position (position_t const &pos_) { pos = pos_; }
|
||||
|
||||
// debug support
|
||||
#if BOOST_WAVE_DUMP_PARSE_TREE != 0
|
||||
// access functions for the tree_to_xml functionality
|
||||
static int get_token_id(lex_token const &t)
|
||||
{ return ID_FROM_TOKEN(token_id(t)); }
|
||||
static string_t get_token_value(lex_token const &t)
|
||||
{ return t.get_value(); }
|
||||
#endif
|
||||
|
||||
// print support
|
||||
void print (std::ostream &stream) const
|
||||
{
|
||||
using namespace std;
|
||||
using namespace boost::wave;
|
||||
stream << setw(16) << left << boost::wave::get_token_name(id) << " ("
|
||||
<< "(#" << token_id(ID_FROM_TOKEN(*this))
|
||||
<< ") at " << get_position().get_file() << " ("
|
||||
<< setw(3) << right << get_position().get_line() << "/"
|
||||
<< setw(2) << right << get_position().get_column()
|
||||
<< "): >";
|
||||
|
||||
for (size_t i = 0; i < value.size(); ++i) {
|
||||
switch (value[i]) {
|
||||
case '\r': stream << "\\r"; break;
|
||||
case '\n': stream << "\\n"; break;
|
||||
case '\t': stream << "\\t"; break;
|
||||
default:
|
||||
stream << value[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
stream << "<";
|
||||
}
|
||||
|
||||
private:
|
||||
boost::wave::token_id id; // the token id
|
||||
string_t value; // the text, which was parsed into this token
|
||||
PositionT pos; // the original file position
|
||||
};
|
||||
|
||||
template <typename PositionT>
|
||||
inline std::ostream &
|
||||
operator<< (std::ostream &stream, slex_token<PositionT> const &object)
|
||||
{
|
||||
object.print(stream);
|
||||
return stream;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace cpp_token_sample
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(SLEX_TOKEN_HPP_53A13BD2_FBAA_444B_9B8B_FCB225C2BBA8_INCLUDED)
|
||||
26
samples/list_includes/build/Jamfile
Normal file
26
samples/list_includes/build/Jamfile
Normal file
@@ -0,0 +1,26 @@
|
||||
# Wave: A Standard compliant C++ preprocessor library
|
||||
#
|
||||
# Boost Wave Library Sample Build Jamfile (list_includes)
|
||||
#
|
||||
# Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
# http://spirit.sourceforge.net/
|
||||
#
|
||||
# Use, modification, and distribution is subject to 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)
|
||||
|
||||
subproject libs/wave/samples/list_includes/build ;
|
||||
|
||||
exe list_includes
|
||||
: ../list_includes.cpp
|
||||
<lib>../../../build/boost_wave
|
||||
<lib>../../../../../libs/program_options/build/boost_program_options
|
||||
<lib>../../../../../libs/filesystem/build/boost_filesystem
|
||||
:
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<vc7.1><*><rtti>off # workaround for compiler bug
|
||||
:
|
||||
<runtime-link>static
|
||||
<threading>single
|
||||
;
|
||||
|
||||
23
samples/list_includes/build/Jamfile.v2
Normal file
23
samples/list_includes/build/Jamfile.v2
Normal file
@@ -0,0 +1,23 @@
|
||||
# Wave: A Standard compliant C++ preprocessor library
|
||||
#
|
||||
# Boost Wave Library Sample Build Jamfile (list_includes)
|
||||
#
|
||||
# Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
# http://spirit.sourceforge.net/
|
||||
#
|
||||
# Use, modification, and distribution is subject to 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)
|
||||
|
||||
exe list_includes
|
||||
: ../list_includes.cpp
|
||||
<lib>../../../build/boost_wave
|
||||
<lib>../../../../../libs/program_options/build/boost_program_options
|
||||
<lib>../../../../../libs/filesystem/build/boost_filesystem
|
||||
:
|
||||
<vc7.1><*><rtti>off # workaround for compiler bug
|
||||
:
|
||||
<runtime-link>static
|
||||
<threading>single
|
||||
;
|
||||
|
||||
286
samples/list_includes/list_includes.cpp
Normal file
286
samples/list_includes/list_includes.cpp
Normal file
@@ -0,0 +1,286 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: List include dependencies of a given source file
|
||||
|
||||
The 'list_includes' sample shows a simple way, how to use the Wave C++
|
||||
preprocessor library to extract a list of included files from a given
|
||||
source file.
|
||||
To get a hint which commandline options are supported, call it with the
|
||||
--help option.
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "list_includes.hpp" // config data
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include required boost libraries
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This sample requires the program_options library written by Vladimir Prus,
|
||||
// which is currently under Boost review.
|
||||
// It is available here: http://boost-sandbox.sourceforge.net/program_options
|
||||
//
|
||||
#include <boost/program_options.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Include Wave itself
|
||||
#include <boost/wave.hpp>
|
||||
|
||||
//#include <boost/wave/util/time_conversion_helper.hpp>
|
||||
//#include <boost/wave/util/file_position.hpp>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
|
||||
#include <boost/wave/cpplexer/cpp_lex_iterator.hpp>
|
||||
|
||||
#include <boost/wave/trace_policies.hpp>
|
||||
#include <boost/wave/cpp_context.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include lexer specifics, import lexer names
|
||||
#if !defined(BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION)
|
||||
#include <boost/wave/cpplexer/re2clex/cpp_re2c_lexer.hpp>
|
||||
#endif // !defined(BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// import required names
|
||||
using namespace boost::spirit;
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::ifstream;
|
||||
using std::ostream;
|
||||
using std::istreambuf_iterator;
|
||||
|
||||
namespace po = boost::program_options;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// print the current version
|
||||
|
||||
int print_version()
|
||||
{
|
||||
// get time of last compilation of this file
|
||||
boost::wave::util::time_conversion_helper compilation_time(__DATE__ " " __TIME__);
|
||||
|
||||
// calculate the number of days since Jan 29 2003
|
||||
// (the day the list_includes project was started)
|
||||
std::tm first_day;
|
||||
|
||||
std::memset (&first_day, 0, sizeof(std::tm));
|
||||
first_day.tm_mon = 0; // Jan
|
||||
first_day.tm_mday = 29; // 29
|
||||
first_day.tm_year = 103; // 2003
|
||||
|
||||
long seconds = long(std::difftime(compilation_time.get_time(),
|
||||
std::mktime(&first_day)));
|
||||
|
||||
cout
|
||||
<< LIST_INCLUDES_VERSION_MAJOR << '.'
|
||||
<< LIST_INCLUDES_VERSION_MINOR << '.'
|
||||
<< LIST_INCLUDES_VERSION_SUBMINOR << '.'
|
||||
<< seconds/(3600*24); // get number of days from seconds
|
||||
return 1; // exit app
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// policy class
|
||||
struct trace_include_files
|
||||
: public boost::wave::trace_policies::default_tracing
|
||||
{
|
||||
trace_include_files(set<string> &files_) : files(files_) {}
|
||||
|
||||
void
|
||||
opened_include_file(string const &filename,
|
||||
std::size_t include_depth, bool is_system_include)
|
||||
{
|
||||
set<string>::iterator it = files.find(filename);
|
||||
if (it == files.end()) {
|
||||
// print indented filename
|
||||
for (size_t i = 0; i < include_depth; ++i)
|
||||
cout << " ";
|
||||
cout << filename << endl;
|
||||
|
||||
files.insert(filename);
|
||||
}
|
||||
}
|
||||
|
||||
set<string> &files;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
int do_actual_work (
|
||||
po::options_and_arguments const opts, po::variables_map const &vm,
|
||||
vector<string> const &pathes, vector<string> const &syspathes)
|
||||
{
|
||||
// current file position is saved for exception handling
|
||||
boost::wave::util::file_position_t current_position;
|
||||
|
||||
try {
|
||||
vector<string> const &arguments = opts.arguments();
|
||||
vector<string>::const_iterator lastfile = arguments.end();
|
||||
|
||||
for (vector<string>::const_iterator file_it = arguments.begin();
|
||||
file_it != lastfile; ++file_it)
|
||||
{
|
||||
ifstream instream((*file_it).c_str());
|
||||
string instring;
|
||||
|
||||
if (!instream.is_open()) {
|
||||
cerr << "Could not open input file: " << *file_it << endl;
|
||||
continue;
|
||||
}
|
||||
instream.unsetf(ios::skipws);
|
||||
instring = string(istreambuf_iterator<char>(instream.rdbuf()),
|
||||
istreambuf_iterator<char>());
|
||||
|
||||
// The template boost::wave::cpplexer::lex_token<> is the token type to be
|
||||
// used by the Wave library.
|
||||
typedef boost::wave::cpplexer::lex_iterator<
|
||||
boost::wave::cpplexer::lex_token<> >
|
||||
lex_iterator_t;
|
||||
typedef boost::wave::context<
|
||||
std::string::iterator, lex_iterator_t,
|
||||
boost::wave::iteration_context_policies::load_file_to_string,
|
||||
trace_include_files
|
||||
> context_t;
|
||||
|
||||
set<string> files;
|
||||
trace_include_files trace(files);
|
||||
|
||||
// The preprocessor iterator shouldn't be constructed directly. It is
|
||||
// to be generated through a wave::context<> object. This wave:context<>
|
||||
// object is additionally to be used to initialize and define different
|
||||
// parameters of the actual preprocessing.
|
||||
// The preprocessing of the input stream is done on the fly behind the
|
||||
// scenes during iteration over the context_t::iterator_t stream.
|
||||
context_t ctx (instring.begin(), instring.end(), (*file_it).c_str(), trace);
|
||||
|
||||
// add include directories to the include path
|
||||
if (vm.count("path")) {
|
||||
vector<string>::const_iterator end = pathes.end();
|
||||
for (vector<string>::const_iterator cit = pathes.begin();
|
||||
cit != end; ++cit)
|
||||
{
|
||||
ctx.add_include_path((*cit).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// add system include directories to the include path
|
||||
if (vm.count("syspath")) {
|
||||
vector<string>::const_iterator end = syspathes.end();
|
||||
for (vector<string>::const_iterator cit = syspathes.begin();
|
||||
cit != end; ++cit)
|
||||
{
|
||||
ctx.add_sysinclude_path((*cit).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// analyze the actual file
|
||||
context_t::iterator_t first = ctx.begin();
|
||||
context_t::iterator_t last = ctx.end();
|
||||
|
||||
cout << "Printing dependency information for: "
|
||||
<< *file_it << endl;
|
||||
|
||||
while (first != last) {
|
||||
current_position = (*first).get_position();
|
||||
++first;
|
||||
}
|
||||
|
||||
// prepend endl before next file
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
catch (boost::wave::cpp_exception &e) {
|
||||
// some preprocessing error
|
||||
cerr
|
||||
<< e.file_name() << "(" << e.line_no() << "): "
|
||||
<< e.description() << endl;
|
||||
return 2;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
// use last recognized token to retrieve the error position
|
||||
cerr
|
||||
<< current_position.get_file()
|
||||
<< "(" << current_position.get_line() << "): "
|
||||
<< "exception caught: " << e.what()
|
||||
<< endl;
|
||||
return 3;
|
||||
}
|
||||
catch (...) {
|
||||
// use last recognized token to retrieve the error position
|
||||
cerr
|
||||
<< current_position.get_file()
|
||||
<< "(" << current_position.get_line() << "): "
|
||||
<< "unexpected exception caught." << endl;
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// here we go!
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
try {
|
||||
// analyze the command line options and arguments
|
||||
vector<string> pathes;
|
||||
vector<string> syspathes;
|
||||
po::options_description desc("Usage: list_includes [options] file ...");
|
||||
|
||||
desc.add_options()
|
||||
("help,h", "", "print out program usage (this message)")
|
||||
("version,v", "", "print the version number")
|
||||
("path,I", po::parameter<vector<string> >("dir", &pathes),
|
||||
"specify additional include directory")
|
||||
("syspath,S", po::parameter<vector<string> >("dir", &syspathes),
|
||||
"specify additional system include directory")
|
||||
;
|
||||
|
||||
po::options_and_arguments opts = po::parse_command_line(argc, argv, desc);
|
||||
po::variables_map vm;
|
||||
|
||||
po::store(opts, vm, desc);
|
||||
if (vm.count("help")) {
|
||||
cout << desc << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("version")) {
|
||||
return print_version();
|
||||
}
|
||||
|
||||
// if there is no input file given, then exit
|
||||
if (0 == opts.arguments().size()) {
|
||||
cerr << "list_includes: No input file given. "
|
||||
<< "Use --help to get a hint." << endl;
|
||||
return 5;
|
||||
}
|
||||
|
||||
// iterate over all given input files
|
||||
return do_actual_work(opts, vm, pathes, syspathes);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
cout << "list_includes: exception caught: " << e.what() << endl;
|
||||
return 6;
|
||||
}
|
||||
catch (...) {
|
||||
cerr << "list_includes: unexpected exception caught." << endl;
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
43
samples/list_includes/list_includes.hpp
Normal file
43
samples/list_includes/list_includes.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: List include dependencies of a given source file
|
||||
Configuration data
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(LIST_INCLUDES_HPP_843DB412_3AA8_4BCF_8081_AA4A5FDE0BE7_INCLUDED)
|
||||
#define LIST_INCLUDES_HPP_843DB412_3AA8_4BCF_8081_AA4A5FDE0BE7_INCLUDED
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include often used files from the stdlib
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include boost config
|
||||
#include <boost/config.hpp> // global configuration information
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// build version
|
||||
#include "list_includes_version.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// configure this app here (global configuration constants)
|
||||
#include "list_includes_config.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include required boost libraries
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/pool/pool_alloc.hpp>
|
||||
|
||||
#endif // !defined(LIST_INCLUDES_HPP_843DB412_3AA8_4BCF_8081_AA4A5FDE0BE7_INCLUDED)
|
||||
228
samples/list_includes/list_includes_config.hpp
Normal file
228
samples/list_includes/list_includes_config.hpp
Normal file
@@ -0,0 +1,228 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Global application configuration of the list_includes sample
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(LIST_INCLUDES_CONFIG_HPP_0DE80E47_8D50_4DFA_9C1C_0EECAA8A934A_INCLUDED)
|
||||
#define LIST_INCLUDES_CONFIG_HPP_0DE80E47_8D50_4DFA_9C1C_0EECAA8A934A_INCLUDED
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement macro scopes (#scope/#endscope), variadics,
|
||||
// placemarkers and well defined token pasting in C++ mode
|
||||
//
|
||||
// To implement these features, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define the macro scoping keywords to be used for the experimental macro
|
||||
// scoping support.
|
||||
//
|
||||
// If the following macros aren't defined, the corresponding default value is
|
||||
// used.
|
||||
//
|
||||
// Note, if you change this, you will have to change the corresponding entries
|
||||
// inside the wave/cpplexer/re2c/cpp.re file too.
|
||||
//
|
||||
//#define BOOST_WAVE_PP_REGION "region"
|
||||
//#define BOOST_WAVE_PP_REGION_UC "REGION" // uppercase of BOOST_WAVE_PP_REGION
|
||||
//#define BOOST_WAVE_PP_ENDREGION "endregion"
|
||||
//#define BOOST_WAVE_PP_IMPORT "import"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define the maximal include nesting depth allowed. If this value isn't
|
||||
// defined it defaults to 1024
|
||||
//
|
||||
// To define a new initial include nesting depth uncomment the following and
|
||||
// supply a new integer value.
|
||||
//
|
||||
//#define BOOST_WAVE_MAX_INCLUDE_LEVEL_DEPTH 1024
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to support variadics and placemarkers
|
||||
//
|
||||
// To implement support variadics and placemarkers uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement a #warning directive as
|
||||
//
|
||||
// To implement #warning directives, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement #pragma once
|
||||
//
|
||||
// To implement #pragma once, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_PRAGMA_ONCE 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement #include_next
|
||||
// Please note, that this is an extension to the C++ Standard.
|
||||
//
|
||||
// To implement #include_next, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_INCLUDE_NEXT 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Undefine the following, to enable some MS specific language extensions:
|
||||
// __int8, __int16, __int32, __int64, __based, __declspec, __cdecl,
|
||||
// __fastcall, __stdcall, __try, __except, __finally, __leave, __inline,
|
||||
// __asm
|
||||
#define BOOST_WAVE_SUPPORT_MS_EXTENSIONS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the message body of the #error and #warning directives to be
|
||||
// preprocessed before the diagnostic is issued.
|
||||
//
|
||||
// Uncommenting the following will preprocess the message bodies of #error and
|
||||
// #warning messages before the error (warning) is issued
|
||||
//
|
||||
#define BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the #pragma directives to be returned to the caller (optionally after
|
||||
// preprocessing the body)
|
||||
//
|
||||
// Undefining the following will skip #pragma directives, so that the caller
|
||||
// will not see them.
|
||||
//
|
||||
#define BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the body of a #pragma directive to be preprocessed before the
|
||||
// directive is returned to the caller.
|
||||
//
|
||||
// Uncommenting the following will preprocess the bodies of #pragma directives
|
||||
//
|
||||
#define BOOST_WAVE_PREPROCESS_PRAGMA_BODY 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow to define macros with the command line syntax (-DMACRO(x)=definition)
|
||||
//
|
||||
// Uncommenting the following will enable the possibility to define macros
|
||||
// based on the command line syntax
|
||||
//
|
||||
#define BOOST_WAVE_ENABLE_COMMANDLINE_MACROS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define the string type to be used to store the token values and the file
|
||||
// names inside a file_position template class
|
||||
//
|
||||
|
||||
// use the following, if you have a fast std::allocator<char>
|
||||
#define BOOST_WAVE_STRINGTYPE wave::util::flex_string< \
|
||||
char, std::char_traits<char>, std::allocator<char>, \
|
||||
wave::util::CowString</*char,*/ \
|
||||
wave::util::AllocatorStringStorage<char> > \
|
||||
> \
|
||||
/**/
|
||||
#include <boost/wave/util/flex_string.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment the following, if you need debug output, the
|
||||
// BOOST_SPIRIT_DEBUG_FLAGS constants below help to fine control the amount of
|
||||
// the generated debug output
|
||||
//#define BOOST_SPIRIT_DEBUG
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// debug rules, subrules and grammars only, for possible flags see
|
||||
// spirit/debug.hpp
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
|
||||
#define BOOST_SPIRIT_DEBUG_FLAGS ( \
|
||||
BOOST_SPIRIT_DEBUG_FLAGS_NODES | \
|
||||
BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES \
|
||||
) \
|
||||
/**/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// debug flags for the pp-iterator library, possible flags (defined in
|
||||
// wave_config.hpp):
|
||||
//
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR 0x0001
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_TIME_CONVERSION 0x0002
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR 0x0004
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_INTLIT_GRAMMAR 0x0008
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR 0x0010
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_DEFINED_GRAMMAR 0x0020
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_PREDEF_MACROS_GRAMMAR 0x0040
|
||||
|
||||
#define BOOST_SPIRIT_DEBUG_FLAGS_CPP (\
|
||||
/* insert the required flags from above */ \
|
||||
) \
|
||||
/**/
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// For all recognized preprocessor statements the output parse trees
|
||||
// formatted as xml are printed. The formatted parse trees are streamed to the
|
||||
// std::ostream defined by the WAVE_DUMP_PARSE_TREE_OUT constant.
|
||||
//
|
||||
// Uncomment the following, if you want to see these parse trees.
|
||||
//
|
||||
//#define BOOST_WAVE_DUMP_PARSE_TREE 1
|
||||
//#define BOOST_WAVE_DUMP_PARSE_TREE_OUT std::cerr
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// For all #if and #elif directives the preprocessed expressions are printed.
|
||||
// These expressions are streamed to the std::ostream defined by the
|
||||
// WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT constant.
|
||||
//
|
||||
// Uncomment the following, if you want to see the preprocessed expressions
|
||||
//
|
||||
//#define BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS 1
|
||||
//#define BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT std::cerr
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to use the separate compilation model for the instantiation
|
||||
// of the C++ lexer objects.
|
||||
//
|
||||
// If this is defined, you should explicitly instantiate the C++ lexer
|
||||
// template with the correct parameters in a separate compilation unit of
|
||||
// your program (see the files instantiate_slex_lexer.cpp and
|
||||
// instantiate_re2c_lexer.cpp).
|
||||
//
|
||||
// To use the lexer inclusion model, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to use the separate compilation model for the instantiation
|
||||
// of the grammar objects.
|
||||
//
|
||||
// If this is defined, you should explicitly instantiate the grammar
|
||||
// templates with the correct parameters in a separate compilation unit of
|
||||
// your program (see the files instantiate_cpp_grammar.cpp).
|
||||
//
|
||||
// To use the grammar inclusion model, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MSVC specific #pragma's
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning (disable: 4355) // 'this' used in base member initializer list
|
||||
#pragma warning (disable: 4800) // forcing value to bool 'true' or 'false'
|
||||
#pragma inline_depth(255)
|
||||
#pragma inline_recursion(on)
|
||||
#endif // defined(BOOST_MSVC)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Now include the cofiguration stuff for the Wave library itself
|
||||
#include <boost/wave/wave_config.hpp>
|
||||
|
||||
#endif // !defined(LIST_INCLUDES_CONFIG_HPP_0DE80E47_8D50_4DFA_9C1C_0EECAA8A934A_INCLUDED)
|
||||
21
samples/list_includes/list_includes_version.hpp
Normal file
21
samples/list_includes/list_includes_version.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: List include dependencies of a given source file version number
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(LIST_INCLUDES_VERSION_HPP_FF662D6C_C3E6_4BEC_A062_5D9BD7415EBF_INCLUDED)
|
||||
#define LIST_INCLUDES_VERSION_HPP_FF662D6C_C3E6_4BEC_A062_5D9BD7415EBF_INCLUDED
|
||||
|
||||
#define LIST_INCLUDES_VERSION_MAJOR 0
|
||||
#define LIST_INCLUDES_VERSION_MINOR 2
|
||||
#define LIST_INCLUDES_VERSION_SUBMINOR 0
|
||||
|
||||
#endif // !defined(LIST_INCLUDES_VERSION_HPP_FF662D6C_C3E6_4BEC_A062_5D9BD7415EBF_INCLUDED)
|
||||
32
samples/waveidl/build/Jamfile
Normal file
32
samples/waveidl/build/Jamfile
Normal file
@@ -0,0 +1,32 @@
|
||||
# Wave: A Standard compliant C++ preprocessor library
|
||||
#
|
||||
# Boost Wave Library Sample Build Jamfile (waveidl)
|
||||
#
|
||||
# Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
# http://spirit.sourceforge.net/
|
||||
#
|
||||
# Use, modification, and distribution is subject to 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)
|
||||
|
||||
subproject libs/wave/samples/waveidl/build ;
|
||||
|
||||
exe waveidl
|
||||
: ../idl.cpp
|
||||
../instantiate_cpp_grammar.cpp
|
||||
../instantiate_defined_grammar.cpp
|
||||
../instantiate_predef_macros.cpp
|
||||
../instantiate_re2c_lexer.cpp
|
||||
../instantiate_re2c_lexer_string.cpp
|
||||
../idllexer/idl.re.cpp
|
||||
<lib>../../../build/boost_wave
|
||||
<lib>../../../../../libs/program_options/build/boost_program_options
|
||||
<lib>../../../../../libs/filesystem/build/boost_filesystem
|
||||
:
|
||||
<sysinclude>$(BOOST_ROOT)
|
||||
<vc7.1><*><rtti>off # workaround for compiler bug
|
||||
:
|
||||
<runtime-link>static
|
||||
<threading>single
|
||||
;
|
||||
|
||||
29
samples/waveidl/build/Jamfile.v2
Normal file
29
samples/waveidl/build/Jamfile.v2
Normal file
@@ -0,0 +1,29 @@
|
||||
# Wave: A Standard compliant C++ preprocessor library
|
||||
#
|
||||
# Boost Wave Library Sample Build Jamfile (waveidl)
|
||||
#
|
||||
# Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
# http://spirit.sourceforge.net/
|
||||
#
|
||||
# Use, modification, and distribution is subject to 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)
|
||||
|
||||
exe waveidl
|
||||
: ../idl.cpp
|
||||
../instantiate_cpp_grammar.cpp
|
||||
../instantiate_defined_grammar.cpp
|
||||
../instantiate_predef_macros.cpp
|
||||
../instantiate_re2c_lexer.cpp
|
||||
../instantiate_re2c_lexer_string.cpp
|
||||
../idllexer/idl.re.cpp
|
||||
<lib>../../../build/boost_wave
|
||||
<lib>../../../../../libs/program_options/build/boost_program_options
|
||||
<lib>../../../../../libs/filesystem/build/boost_filesystem
|
||||
:
|
||||
<vc7.1><*><rtti>off # workaround for compiler bug
|
||||
:
|
||||
<runtime-link>static
|
||||
<threading>single
|
||||
;
|
||||
|
||||
521
samples/waveidl/idl.cpp
Normal file
521
samples/waveidl/idl.cpp
Normal file
@@ -0,0 +1,521 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "idl.hpp" // global configuration
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This sample requires the program_options library written by Vladimir Prus,
|
||||
// which is already accepted into Boost, but not included with the
|
||||
// distribution yet.
|
||||
// It is available here: http://boost-sandbox.sourceforge.net/program_options.
|
||||
//
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Include Wave itself
|
||||
#include <boost/wave.hpp>
|
||||
|
||||
// Include the lexer related stuff
|
||||
#include <boost/wave/token_ids.hpp> // token Id's
|
||||
#include <boost/wave/cpplexer/cpp_lex_token.hpp> // token type
|
||||
|
||||
#include "idllexer/idl_lex_iterator.hpp" // lexer type
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include lexer specifics, import lexer names
|
||||
//
|
||||
#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION == 0
|
||||
#include "idllexer/idl_re2c_lexer.hpp"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include the grammar definitions, if these shouldn't be compiled separately
|
||||
// (ATTENTION: _very_ large compilation times!)
|
||||
//
|
||||
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION == 0
|
||||
#include <boost/wave/grammars/cpp_intlit_grammar.hpp>
|
||||
#include <boost/wave/grammars/cpp_chlit_grammar.hpp>
|
||||
#include <boost/wave/grammars/cpp_grammar.hpp>
|
||||
#include <boost/wave/grammars/cpp_expression_grammar.hpp>
|
||||
#include <boost/wave/grammars/cpp_predef_macros_grammar.hpp>
|
||||
#include <boost/wave/grammars/cpp_defined_grammar.hpp>
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// import required names
|
||||
using namespace boost::spirit;
|
||||
|
||||
using std::string;
|
||||
using std::pair;
|
||||
using std::vector;
|
||||
using std::getline;
|
||||
using std::ifstream;
|
||||
using std::cout;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::ostream;
|
||||
using std::istreambuf_iterator;
|
||||
|
||||
namespace po = boost::program_options;
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// print the current version
|
||||
int print_version()
|
||||
{
|
||||
typedef boost::wave::idllexer::lex_iterator<
|
||||
boost::wave::cpplexer::lex_token<> >
|
||||
lex_iterator_t;
|
||||
typedef boost::wave::context<std::string::iterator, lex_iterator_t>
|
||||
context_t;
|
||||
|
||||
string version (context_t::get_version_string());
|
||||
cout
|
||||
<< version.substr(1, version.size()-2) // strip quotes
|
||||
<< " (" << IDL_VERSION_DATE << ")" // add date
|
||||
<< endl;
|
||||
return 0; // exit app
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// print the copyright statement
|
||||
int print_copyright()
|
||||
{
|
||||
char const *copyright[] = {
|
||||
"",
|
||||
"Sample: IDL oriented preprocessor",
|
||||
"Based on: Wave, A Standard conformant C++ preprocessor library",
|
||||
"Copyright (c) 2001-2004 Hartmut Kaiser",
|
||||
"It is hosted by http://spirit.sourceforge.net/.",
|
||||
"",
|
||||
"Use, modification and distribution is subject to 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)",
|
||||
0
|
||||
};
|
||||
|
||||
for (int i = 0; 0 != copyright[i]; ++i)
|
||||
cout << copyright[i] << endl;
|
||||
|
||||
return 0; // exit app
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace cmd_line_util {
|
||||
|
||||
// Additional command line parser which interprets '@something' as an
|
||||
// option "config-file" with the value "something".
|
||||
pair<string, string> at_option_parser(string const&s)
|
||||
{
|
||||
if ('@' == s[0])
|
||||
return std::make_pair(string("config-file"), s.substr(1));
|
||||
else
|
||||
return pair<string, string>();
|
||||
}
|
||||
|
||||
// class, which keeps include file information from the command line
|
||||
class include_paths {
|
||||
public:
|
||||
include_paths() : seen_separator(false) {}
|
||||
|
||||
vector<string> paths; // stores user paths
|
||||
vector<string> syspaths; // stores system paths
|
||||
bool seen_separator; // command line contains a '-I-' option
|
||||
|
||||
// Function which validates additional tokens from command line.
|
||||
static void
|
||||
validate(boost::any &v, vector<string> const &tokens)
|
||||
{
|
||||
if (v.empty())
|
||||
v = boost::any(include_paths());
|
||||
|
||||
include_paths *p = boost::any_cast<include_paths>(&v);
|
||||
|
||||
BOOST_SPIRIT_ASSERT(p);
|
||||
// Assume only one path per '-I' occurrence.
|
||||
string t = tokens[0];
|
||||
if (t == "-") {
|
||||
// found -I- option, so switch behaviour
|
||||
p->seen_separator = true;
|
||||
}
|
||||
else if (p->seen_separator) {
|
||||
// store this path as a system path
|
||||
p->syspaths.push_back(t);
|
||||
}
|
||||
else {
|
||||
// store this path as an user path
|
||||
p->paths.push_back(t);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Workaround for a problem in the program_options library: all options
|
||||
// stored in a variables_map, which have an assigned validator function
|
||||
// need an extraction operator.
|
||||
std::istream& operator>>(std::istream& is, include_paths& p)
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
// Read all options from a given config file, parse and add them to the
|
||||
// given variables_map
|
||||
void read_config_file_options(string const &filename,
|
||||
po::options_description const &desc, po::variables_map &vm,
|
||||
bool may_fail = false)
|
||||
{
|
||||
ifstream ifs(filename.c_str());
|
||||
|
||||
if (!ifs.is_open()) {
|
||||
if (!may_fail) {
|
||||
cerr << filename
|
||||
<< ": command line warning: config file not found"
|
||||
<< endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
vector<string> options;
|
||||
string line;
|
||||
|
||||
while (std::getline(ifs, line)) {
|
||||
// skip empty lines
|
||||
string::size_type pos = line.find_first_not_of(" \t");
|
||||
if (pos == string::npos)
|
||||
continue;
|
||||
|
||||
// skip comment lines
|
||||
if ('#' != line[pos])
|
||||
options.push_back(line);
|
||||
}
|
||||
|
||||
if (options.size() > 0) {
|
||||
po::options_and_arguments oa = po::parse_command_line(options, desc);
|
||||
|
||||
po::store(oa, vm, desc);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// do the actual preprocessing
|
||||
int do_actual_work (po::options_and_arguments const opts,
|
||||
po::variables_map const &vm)
|
||||
{
|
||||
// current file position is saved for exception handling
|
||||
boost::wave::util::file_position_t current_position;
|
||||
|
||||
try {
|
||||
// process the given file
|
||||
string file_name(opts.arguments().front());
|
||||
ifstream instream(file_name.c_str());
|
||||
string instring;
|
||||
|
||||
if (!instream.is_open()) {
|
||||
cerr << "waveidl: could not open input file: " << file_name << endl;
|
||||
return -1;
|
||||
}
|
||||
instream.unsetf(std::ios::skipws);
|
||||
|
||||
#if defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS)
|
||||
// this is known to be very slow for large files on some systems
|
||||
copy (istream_iterator<char>(instream),
|
||||
istream_iterator<char>(),
|
||||
inserter(instring, instring.end()));
|
||||
#else
|
||||
instring = string(istreambuf_iterator<char>(instream.rdbuf()),
|
||||
istreambuf_iterator<char>());
|
||||
#endif
|
||||
|
||||
// This sample uses the lex_iterator and lex_token types predefined with
|
||||
// the Wave library, but it is possible to use your own types.
|
||||
typedef boost::wave::idllexer::lex_iterator<
|
||||
boost::wave::cpplexer::lex_token<> >
|
||||
lex_iterator_t;
|
||||
typedef boost::wave::context<std::string::iterator, lex_iterator_t>
|
||||
context_t;
|
||||
|
||||
// The C++ preprocessor iterators shouldn't be constructed directly. They
|
||||
// are to be generated through a boost::wave::context<> object. This
|
||||
// boost::wave::context object is additionally to be used to initialize and
|
||||
// define different parameters of the actual preprocessing.
|
||||
// The preprocessing of the input stream is done on the fly behind the
|
||||
// scenes during iteration over the context_t::iterator_t stream.
|
||||
context_t ctx (instring.begin(), instring.end(), file_name.c_str());
|
||||
|
||||
// add include directories to the system include search paths
|
||||
if (vm.count("sysinclude")) {
|
||||
vector<string> syspaths = vm["sysinclude"].as<vector<string> >();
|
||||
|
||||
vector<string>::const_iterator end = syspaths.end();
|
||||
for (vector<string>::const_iterator cit = syspaths.begin();
|
||||
cit != end; ++cit)
|
||||
{
|
||||
ctx.add_sysinclude_path((*cit).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// add include directories to the include search paths
|
||||
if (vm.count("include")) {
|
||||
cmd_line_util::include_paths const &ip =
|
||||
vm["include"].as<cmd_line_util::include_paths>();
|
||||
vector<string>::const_iterator end = ip.paths.end();
|
||||
|
||||
for (vector<string>::const_iterator cit = ip.paths.begin();
|
||||
cit != end; ++cit)
|
||||
{
|
||||
ctx.add_include_path((*cit).c_str());
|
||||
}
|
||||
|
||||
// if on the command line was given -I- , this has to be propagated
|
||||
if (ip.seen_separator)
|
||||
ctx.set_sysinclude_delimiter();
|
||||
|
||||
// add system include directories to the include path
|
||||
vector<string>::const_iterator sysend = ip.syspaths.end();
|
||||
for (vector<string>::const_iterator syscit = ip.syspaths.begin();
|
||||
syscit != sysend; ++syscit)
|
||||
{
|
||||
ctx.add_sysinclude_path((*syscit).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// add additional defined macros
|
||||
if (vm.count("define")) {
|
||||
vector<string> macros = vm["define"].as<vector<string> >();
|
||||
vector<string>::const_iterator end = macros.end();
|
||||
for (vector<string>::const_iterator cit = macros.begin();
|
||||
cit != end; ++cit)
|
||||
{
|
||||
ctx.add_macro_definition(*cit);
|
||||
}
|
||||
}
|
||||
|
||||
// add additional predefined macros
|
||||
if (vm.count("predefine")) {
|
||||
vector<string> predefmacros = vm["predefine"].as<vector<string> >();
|
||||
vector<string>::const_iterator end = predefmacros.end();
|
||||
for (vector<string>::const_iterator cit = predefmacros.begin();
|
||||
cit != end; ++cit)
|
||||
{
|
||||
ctx.add_macro_definition(*cit, true);
|
||||
}
|
||||
}
|
||||
|
||||
// undefine specified macros
|
||||
if (vm.count("undefine")) {
|
||||
vector<string> undefmacros = vm["undefine"].as<vector<string> >();
|
||||
vector<string>::const_iterator end = undefmacros.end();
|
||||
for (vector<string>::const_iterator cit = undefmacros.begin();
|
||||
cit != end; ++cit)
|
||||
{
|
||||
ctx.remove_macro_definition((*cit).c_str(), true);
|
||||
}
|
||||
}
|
||||
|
||||
// open the output file
|
||||
std::ofstream output;
|
||||
|
||||
if (vm.count("output")) {
|
||||
// try to open the file, where to put the preprocessed output
|
||||
string out_file (vm["output"].as<string>());
|
||||
|
||||
output.open(out_file.c_str());
|
||||
if (!output.is_open()) {
|
||||
cerr << "waveidl: could not open output file: " << out_file
|
||||
<< endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// output the preprocessed result to std::cout
|
||||
output.copyfmt(cout);
|
||||
output.clear(cout.rdstate());
|
||||
static_cast<std::basic_ios<char> &>(output).rdbuf(cout.rdbuf());
|
||||
}
|
||||
|
||||
// analyze the input file
|
||||
context_t::iterator_t first = ctx.begin();
|
||||
context_t::iterator_t last = ctx.end();
|
||||
|
||||
// loop over all generated tokens outputing the generated text
|
||||
while (first != last) {
|
||||
// print out the string representation of this token (skip comments)
|
||||
using namespace boost::wave;
|
||||
|
||||
// store the last known good token position
|
||||
current_position = (*first).get_position();
|
||||
|
||||
token_id id = token_id(*first);
|
||||
|
||||
if (T_CPPCOMMENT == id || T_NEWLINE == id) {
|
||||
// C++ comment tokens contain the trailing newline
|
||||
output << endl;
|
||||
}
|
||||
else if (id != T_CCOMMENT) {
|
||||
// print out the current token value
|
||||
output << (*first).get_value();
|
||||
}
|
||||
++first; // advance to the next token
|
||||
}
|
||||
}
|
||||
catch (boost::wave::cpp_exception &e) {
|
||||
// some preprocessing error
|
||||
cerr
|
||||
<< e.file_name() << "(" << e.line_no() << "): "
|
||||
<< e.description() << endl;
|
||||
return 1;
|
||||
}
|
||||
catch (boost::wave::cpplexer::lexing_exception &e) {
|
||||
// some lexing error
|
||||
cerr
|
||||
<< e.file_name() << "(" << e.line_no() << "): "
|
||||
<< e.description() << endl;
|
||||
return 2;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
// use last recognized token to retrieve the error position
|
||||
cerr
|
||||
<< current_position.get_file()
|
||||
<< "(" << current_position.get_line() << "): "
|
||||
<< "exception caught: " << e.what()
|
||||
<< endl;
|
||||
return 3;
|
||||
}
|
||||
catch (...) {
|
||||
// use last recognized token to retrieve the error position
|
||||
cerr
|
||||
<< current_position.get_file()
|
||||
<< "(" << current_position.get_line() << "): "
|
||||
<< "unexpected exception caught." << endl;
|
||||
return 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// main entry point
|
||||
int
|
||||
main (int argc, char const *argv[])
|
||||
{
|
||||
try {
|
||||
// analyze the command line options and arguments
|
||||
vector<string> cfg_files;
|
||||
|
||||
// declare the options allowed from the command line only
|
||||
po::options_description desc_cmdline ("Options allowed on the command line only");
|
||||
|
||||
desc_cmdline.add_options()
|
||||
("help,h", "", "print out program usage (this message)")
|
||||
("version,v", "", "print the version number")
|
||||
("copyright,c", "", "print out the copyright statement")
|
||||
("config-file", po::parameter("filepath", &cfg_files),
|
||||
"specify a config file (alternatively: @filepath)")
|
||||
;
|
||||
|
||||
// declare the options allowed on command line and in config files
|
||||
po::options_description desc_generic ("Options allowed additionally in a config file");
|
||||
|
||||
desc_generic.add_options()
|
||||
("output,o", "path", "specify a file to use for output instead of stdout")
|
||||
("include,I", "path", "specify an additional include directory").
|
||||
validator(&cmd_line_util::include_paths::validate)
|
||||
("sysinclude,S", po::parameter<vector<string> >("syspath"),
|
||||
"specify an additional system include directory")
|
||||
("define,D", po::parameter<vector<string> >("macro[=[value]]"),
|
||||
"specify a macro to define")
|
||||
("predefine,P", po::parameter<vector<string> >("macro[=[value]]"),
|
||||
"specify a macro to predefine")
|
||||
("undefine,U", po::parameter<vector<string> >("macro"),
|
||||
"specify a macro to undefine")
|
||||
;
|
||||
|
||||
// combine the options for the different usage schemes
|
||||
po::options_description desc_overall_cmdline;
|
||||
|
||||
desc_overall_cmdline.add(desc_cmdline);
|
||||
desc_overall_cmdline.add(desc_generic);
|
||||
|
||||
po::options_description desc_overall_cfgfile;
|
||||
|
||||
desc_overall_cfgfile.add(desc_generic);
|
||||
|
||||
// parse command line and store results
|
||||
po::options_and_arguments opts = po::parse_command_line(argc, argv,
|
||||
desc_overall_cmdline, 0, cmd_line_util::at_option_parser);
|
||||
po::variables_map vm;
|
||||
|
||||
po::store(opts, vm, desc_overall_cmdline);
|
||||
|
||||
// Try to find a waveidl.cfg in the same directory as the executable was
|
||||
// started from. If this exists, treat it as a wave config file
|
||||
fs::path filename(argv[0], fs::native);
|
||||
|
||||
filename = filename.branch_path() / "waveidl.cfg";
|
||||
cmd_line_util::read_config_file_options(filename.string(),
|
||||
desc_overall_cfgfile, vm, true);
|
||||
|
||||
// if there is specified at least one config file, parse it and add the
|
||||
// options to the main variables_map
|
||||
if (vm.count("config-file")) {
|
||||
vector<string>::const_iterator end = cfg_files.end();
|
||||
for (vector<string>::const_iterator cit = cfg_files.begin();
|
||||
cit != end; ++cit)
|
||||
{
|
||||
// parse a single config file and store the results
|
||||
cmd_line_util::read_config_file_options(*cit,
|
||||
desc_overall_cfgfile, vm);
|
||||
}
|
||||
}
|
||||
|
||||
// ... act as required
|
||||
if (vm.count("help")) {
|
||||
po::options_description desc_help (
|
||||
"Usage: waveidl [options] [@config-file(s)] file");
|
||||
|
||||
desc_help.add(desc_cmdline);
|
||||
desc_help.add(desc_generic);
|
||||
cout << desc_help << endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (vm.count("version")) {
|
||||
return print_version();
|
||||
}
|
||||
|
||||
if (vm.count("copyright")) {
|
||||
return print_copyright();
|
||||
}
|
||||
|
||||
// if there is no input file given, then exit
|
||||
if (0 == opts.arguments().size()) {
|
||||
cerr << "waveidl: no input file given, "
|
||||
<< "use --help to get a hint." << endl;
|
||||
return 5;
|
||||
}
|
||||
|
||||
// preprocess the given input file
|
||||
return do_actual_work(opts, vm);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
cout << "waveidl: exception caught: " << e.what() << endl;
|
||||
return 6;
|
||||
}
|
||||
catch (...) {
|
||||
cerr << "waveidl: unexpected exception caught." << endl;
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
|
||||
46
samples/waveidl/idl.hpp
Normal file
46
samples/waveidl/idl.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(IDL_HPP_FC7EE131_5CE9_43F2_A713_8D9BBC3C8477_INCLUDED)
|
||||
#define IDL_HPP_FC7EE131_5CE9_43F2_A713_8D9BBC3C8477_INCLUDED
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// This file may be used as a precompiled header (if applicable)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include often used files from the stdlib
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include boost config
|
||||
#include <boost/config.hpp> // global configuration information
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// build version
|
||||
#include "idl_version.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// configure this app here (global configuration constants)
|
||||
#include "idl_config.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// include required boost libraries
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/pool/pool_alloc.hpp>
|
||||
|
||||
#endif // !defined(IDL_HPP_FC7EE131_5CE9_43F2_A713_8D9BBC3C8477_INCLUDED)
|
||||
207
samples/waveidl/idl_config.hpp
Normal file
207
samples/waveidl/idl_config.hpp
Normal file
@@ -0,0 +1,207 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
Global application configuration of the Wave driver command
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(IDL_CONFIG_HPP_012D7524_FF3F_482F_9123_91966C72F4EA_INCLUDED)
|
||||
#define IDL_CONFIG_HPP_012D7524_FF3F_482F_9123_91966C72F4EA_INCLUDED
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement macro scopes (#scope/#endscope), variadics,
|
||||
// placemarkers and well defined token pasting in C++ mode
|
||||
//
|
||||
// To implement these features, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_ENABLE_CPP0X_EXTENSIONS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define the maximal include nesting depth allowed. If this value isn't
|
||||
// defined it defaults to 1024
|
||||
//
|
||||
// To define a new initial include nesting depth uncomment the following and
|
||||
// supply a new integer value.
|
||||
//
|
||||
//#define BOOST_WAVE_MAX_INCLUDE_LEVEL_DEPTH 1024
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to support variadics and placemarkers
|
||||
//
|
||||
// To implement support variadics and placemarkers uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement a #warning directive as
|
||||
//
|
||||
// To implement #warning directives, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement #pragma once
|
||||
//
|
||||
// To implement #pragma once, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_PRAGMA_ONCE 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to implement #include_next
|
||||
// Please note, that this is an extension to the C++ Standard.
|
||||
//
|
||||
// To implement #include_next, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SUPPORT_INCLUDE_NEXT 0
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the message body of the #error and #warning directives to be
|
||||
// preprocessed before the diagnostic is issued.
|
||||
//
|
||||
// Uncommenting the following will preprocess the message bodies of #error and
|
||||
// #warning messages before the error (warning) is issued
|
||||
//
|
||||
#define BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the #pragma directives to be returned to the caller (optionally after
|
||||
// preprocessing the body)
|
||||
//
|
||||
// Undefining the following will skip #pragma directives, so that the caller
|
||||
// will not see them.
|
||||
//
|
||||
#define BOOST_WAVE_EMIT_PRAGMA_DIRECTIVES 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow the body of a #pragma directive to be preprocessed before the
|
||||
// directive is returned to the caller.
|
||||
//
|
||||
// Uncommenting the following will preprocess the bodies of #pragma directives
|
||||
//
|
||||
#define BOOST_WAVE_PREPROCESS_PRAGMA_BODY 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Allow to define macros with the command line syntax (-DMACRO(x)=definition)
|
||||
//
|
||||
// Uncommenting the following will enable the possibility to define macros
|
||||
// based on the command line syntax
|
||||
//
|
||||
#define BOOST_WAVE_ENABLE_COMMANDLINE_MACROS 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Define the string type to be used to store the token values and the file
|
||||
// names inside a file_position template class
|
||||
//
|
||||
|
||||
// use the following, if you have a fast std::allocator<char>
|
||||
#define BOOST_WAVE_STRINGTYPE boost::wave::util::flex_string< \
|
||||
char, std::char_traits<char>, std::allocator<char>, \
|
||||
boost::wave::util::CowString< \
|
||||
boost::wave::util::AllocatorStringStorage<char> > \
|
||||
> \
|
||||
/**/
|
||||
#include <boost/wave/util/flex_string.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Uncomment the following, if you need debug output, the
|
||||
// BOOST_SPIRIT_DEBUG_FLAGS constants below help to fine control the amount of
|
||||
// the generated debug output
|
||||
//#define BOOST_SPIRIT_DEBUG
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// debug rules, subrules and grammars only, for possible flags see
|
||||
// spirit/debug.hpp
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
|
||||
#define BOOST_SPIRIT_DEBUG_FLAGS ( \
|
||||
BOOST_SPIRIT_DEBUG_FLAGS_NODES | \
|
||||
BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES \
|
||||
) \
|
||||
/**/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// debug flags for the pp-iterator library, possible flags (defined in
|
||||
// wave_config.hpp):
|
||||
//
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR 0x0001
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_TIME_CONVERSION 0x0002
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR 0x0004
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_INTLIT_GRAMMAR 0x0008
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_CHLIT_GRAMMAR 0x0010
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_DEFINED_GRAMMAR 0x0020
|
||||
// #define BOOST_SPIRIT_DEBUG_FLAGS_PREDEF_MACROS_GRAMMAR 0x0040
|
||||
|
||||
#define BOOST_SPIRIT_DEBUG_FLAGS_CPP (\
|
||||
/* insert the required flags from above */ \
|
||||
) \
|
||||
/**/
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// For all recognized preprocessor statements the output parse trees
|
||||
// formatted as xml are printed. The formatted parse trees are streamed to the
|
||||
// std::ostream defined by the BOOST_WAVE_DUMP_PARSE_TREE_OUT constant.
|
||||
//
|
||||
// Uncomment the following, if you want to see these parse trees.
|
||||
//
|
||||
//#define BOOST_WAVE_DUMP_PARSE_TREE 1
|
||||
//#define BOOST_WAVE_DUMP_PARSE_TREE_OUT std::cerr
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// For all #if and #elif directives the preprocessed expressions are printed.
|
||||
// These expressions are streamed to the std::ostream defined by the
|
||||
// BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT constant.
|
||||
//
|
||||
// Uncomment the following, if you want to see the preprocessed expressions
|
||||
//
|
||||
//#define BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS 1
|
||||
//#define BOOST_WAVE_DUMP_CONDITIONAL_EXPRESSIONS_OUT std::cerr
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to use the separate compilation model for the instantiation
|
||||
// of the C++ lexer objects.
|
||||
//
|
||||
// If this is defined, you should explicitly instantiate the C++ lexer
|
||||
// template with the correct parameters in a separate compilation unit of
|
||||
// your program (see the files instantiate_slex_lexer.cpp and
|
||||
// instantiate_re2c_lexer.cpp).
|
||||
//
|
||||
// To use the lexer inclusion model, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Decide, whether to use the separate compilation model for the instantiation
|
||||
// of the grammar objects.
|
||||
//
|
||||
// If this is defined, you should explicitly instantiate the grammar
|
||||
// templates with the correct parameters in a separate compilation unit of
|
||||
// your program (see the files instantiate_cpp_grammar.cpp).
|
||||
//
|
||||
// To use the grammar inclusion model, uncomment the following
|
||||
//
|
||||
#define BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION 1
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MSVC specific #pragma's
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning (disable: 4355) // 'this' used in base member initializer list
|
||||
#pragma warning (disable: 4800) // forcing value to bool 'true' or 'false'
|
||||
#pragma inline_depth(255)
|
||||
#pragma inline_recursion(on)
|
||||
#endif // defined(BOOST_MSVC)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Now include the cofiguration stuff for the Wave library itself
|
||||
#include <boost/wave/wave_config.hpp>
|
||||
|
||||
#endif // !defined(IDL_CONFIG_HPP_012D7524_FF3F_482F_9123_91966C72F4EA_INCLUDED)
|
||||
24
samples/waveidl/idl_version.hpp
Normal file
24
samples/waveidl/idl_version.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(IDL_VERSION_HPP_780C1190_3107_440B_B303_B687A449749B_INCLUDED)
|
||||
#define IDL_VERSION_HPP_780C1190_3107_440B_B303_B687A449749B_INCLUDED
|
||||
|
||||
#include <boost/wave/wave_version.hpp>
|
||||
|
||||
#define IDL_VERSION_MAJOR BOOST_WAVE_VERSION_MAJOR
|
||||
#define IDL_VERSION_MINOR BOOST_WAVE_VERSION_MINOR
|
||||
#define IDL_VERSION_SUBMINOR BOOST_WAVE_VERSION_SUBMINOR
|
||||
#define IDL_VERSION_DATE 20040124L
|
||||
|
||||
#endif // !defined(IDL_VERSION_HPP_780C1190_3107_440B_B303_B687A449749B_INCLUDED)
|
||||
561
samples/waveidl/idllexer/idl.re
Normal file
561
samples/waveidl/idllexer/idl.re
Normal file
@@ -0,0 +1,561 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL lexer
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if defined(BOOST_HAS_UNISTD_H)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
// reuse the token ids and re2c helper functions from the default C++ lexer
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/cpplexer/re2clex/aq.hpp>
|
||||
#include <boost/wave/cpplexer/re2clex/scanner.hpp>
|
||||
|
||||
#include "idl.re.hpp"
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__COMO__)
|
||||
#pragma warning (disable: 4101) // 'foo' : unreferenced local variable
|
||||
#pragma warning (disable: 4102) // 'foo' : unreferenced label
|
||||
#if BOOST_WORKAROUND(_MSC_VER, BOOST_TESTED_AT(1310))
|
||||
// VC upto 7.1 is not able to optimize this file
|
||||
#pragma optimize("", off)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define BSIZE 196608
|
||||
|
||||
#define YYCTYPE uchar
|
||||
#define YYCURSOR cursor
|
||||
#define YYLIMIT s->lim
|
||||
#define YYMARKER s->ptr
|
||||
#define YYFILL(n) {cursor = fill(s, cursor);}
|
||||
|
||||
//#define RET(i) {s->cur = cursor; return (i);}
|
||||
#define RET(i) \
|
||||
{ \
|
||||
s->line += count_backslash_newlines(s, cursor); \
|
||||
s->cur = cursor; \
|
||||
return (i); \
|
||||
} \
|
||||
/**/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace idllexer {
|
||||
namespace re2clex {
|
||||
|
||||
#define RE2C_ASSERT BOOST_ASSERT
|
||||
|
||||
int
|
||||
get_one_char(boost::wave::cpplexer::re2clex::Scanner *s)
|
||||
{
|
||||
using namespace boost::wave::cpplexer::re2clex;
|
||||
if (s->fd != -1) {
|
||||
uchar val;
|
||||
|
||||
if (read(s->fd, &val, sizeof(val)))
|
||||
return val;
|
||||
}
|
||||
else if (0 != s->act) {
|
||||
RE2C_ASSERT(s->first != 0 && s->last != 0);
|
||||
RE2C_ASSERT(s->first <= s->act && s->act <= s->last);
|
||||
if (s->act < s->last)
|
||||
return *(s->act)++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::ptrdiff_t
|
||||
rewind_stream (boost::wave::cpplexer::re2clex::Scanner *s, int cnt)
|
||||
{
|
||||
if (s->fd != -1) {
|
||||
return lseek(s->fd, cnt, SEEK_CUR);
|
||||
}
|
||||
else if (0 != s->act) {
|
||||
RE2C_ASSERT(s->first != 0 && s->last != 0);
|
||||
s->act += cnt;
|
||||
RE2C_ASSERT(s->first <= s->act && s->act <= s->last);
|
||||
return s->act - s->first;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
get_first_eol_offset(boost::wave::cpplexer::re2clex::Scanner* s)
|
||||
{
|
||||
if (!AQ_EMPTY(s->eol_offsets))
|
||||
{
|
||||
return s->eol_offsets->queue[s->eol_offsets->head];
|
||||
}
|
||||
else
|
||||
{
|
||||
return (unsigned int)-1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
adjust_eol_offsets(boost::wave::cpplexer::re2clex::Scanner* s,
|
||||
std::size_t adjustment)
|
||||
{
|
||||
boost::wave::cpplexer::re2clex::aq_queue q;
|
||||
std::size_t i;
|
||||
|
||||
if (!s->eol_offsets)
|
||||
s->eol_offsets = boost::wave::cpplexer::re2clex::aq_create();
|
||||
|
||||
q = s->eol_offsets;
|
||||
|
||||
if (AQ_EMPTY(q))
|
||||
return;
|
||||
|
||||
i = q->head;
|
||||
while (i != q->tail)
|
||||
{
|
||||
if (adjustment > q->queue[i])
|
||||
q->queue[i] = 0;
|
||||
else
|
||||
q->queue[i] -= adjustment;
|
||||
++i;
|
||||
if (i == q->max_size)
|
||||
i = 0;
|
||||
}
|
||||
if (adjustment > q->queue[i])
|
||||
q->queue[i] = 0;
|
||||
else
|
||||
q->queue[i] -= adjustment;
|
||||
}
|
||||
|
||||
int
|
||||
count_backslash_newlines(boost::wave::cpplexer::re2clex::Scanner *s,
|
||||
boost::wave::cpplexer::re2clex::uchar *cursor)
|
||||
{
|
||||
using namespace boost::wave::cpplexer::re2clex;
|
||||
|
||||
std::size_t diff, offset;
|
||||
int skipped = 0;
|
||||
|
||||
/* figure out how many backslash-newlines skipped over unknowingly. */
|
||||
diff = cursor - s->bot;
|
||||
offset = get_first_eol_offset(s);
|
||||
while (offset <= diff && offset != (unsigned int)-1)
|
||||
{
|
||||
skipped++;
|
||||
boost::wave::cpplexer::re2clex::aq_pop(s->eol_offsets);
|
||||
offset = get_first_eol_offset(s);
|
||||
}
|
||||
return skipped;
|
||||
}
|
||||
|
||||
boost::wave::cpplexer::re2clex::uchar *
|
||||
fill(boost::wave::cpplexer::re2clex::Scanner *s,
|
||||
boost::wave::cpplexer::re2clex::uchar *cursor)
|
||||
{
|
||||
using namespace boost::wave::cpplexer::re2clex;
|
||||
|
||||
if(!s->eof)
|
||||
{
|
||||
uchar* p;
|
||||
std::ptrdiff_t cnt = s->tok - s->bot;
|
||||
if(cnt)
|
||||
{
|
||||
memcpy(s->bot, s->tok, s->lim - s->tok);
|
||||
s->tok = s->bot;
|
||||
s->ptr -= cnt;
|
||||
cursor -= cnt;
|
||||
s->lim -= cnt;
|
||||
adjust_eol_offsets(s, cnt);
|
||||
}
|
||||
|
||||
if((s->top - s->lim) < BSIZE)
|
||||
{
|
||||
uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
|
||||
if (buf == 0)
|
||||
{
|
||||
if (0 != s->error_proc)
|
||||
(*s->error_proc)(s, "Out of memory!");
|
||||
else
|
||||
printf("Out of memory!\n");
|
||||
|
||||
/* get the scanner to stop */
|
||||
*cursor = 0;
|
||||
return cursor;
|
||||
}
|
||||
|
||||
memcpy(buf, s->tok, s->lim - s->tok);
|
||||
s->tok = buf;
|
||||
s->ptr = &buf[s->ptr - s->bot];
|
||||
cursor = &buf[cursor - s->bot];
|
||||
s->lim = &buf[s->lim - s->bot];
|
||||
s->top = &s->lim[BSIZE];
|
||||
free(s->bot);
|
||||
s->bot = buf;
|
||||
}
|
||||
|
||||
if (s->fd != -1) {
|
||||
if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE)
|
||||
{
|
||||
s->eof = &s->lim[cnt]; *(s->eof)++ = '\0';
|
||||
}
|
||||
}
|
||||
else if (s->act != 0) {
|
||||
cnt = s->last - s->act;
|
||||
if (cnt > BSIZE)
|
||||
cnt = BSIZE;
|
||||
memcpy(s->lim, s->act, cnt);
|
||||
s->act += cnt;
|
||||
if (cnt != BSIZE)
|
||||
{
|
||||
s->eof = &s->lim[cnt]; *(s->eof)++ = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/* backslash-newline erasing time */
|
||||
|
||||
/* first scan for backslash-newline and erase them */
|
||||
for (p = s->lim; p < s->lim + cnt - 2; ++p)
|
||||
{
|
||||
if (*p == '\\')
|
||||
{
|
||||
if (*(p+1) == '\n')
|
||||
{
|
||||
memmove(p, p + 2, s->lim + cnt - p - 2);
|
||||
cnt -= 2;
|
||||
--p;
|
||||
boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
|
||||
p - s->bot + 1);
|
||||
}
|
||||
else if (*(p+1) == '\r')
|
||||
{
|
||||
if (*(p+2) == '\n')
|
||||
{
|
||||
memmove(p, p + 3, s->lim + cnt - p - 3);
|
||||
cnt -= 3;
|
||||
--p;
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(p, p + 2, s->lim + cnt - p - 2);
|
||||
cnt -= 2;
|
||||
--p;
|
||||
}
|
||||
boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
|
||||
p - s->bot + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check to see if what we just read ends in a backslash */
|
||||
if (cnt >= 2)
|
||||
{
|
||||
uchar last = s->lim[cnt-1];
|
||||
uchar last2 = s->lim[cnt-2];
|
||||
/* check \ EOB */
|
||||
if (last == '\\')
|
||||
{
|
||||
int next = get_one_char(s);
|
||||
/* check for \ \n or \ \r or \ \r \n straddling the border */
|
||||
if (next == '\n')
|
||||
{
|
||||
--cnt; /* chop the final \, we've already read the \n. */
|
||||
boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
|
||||
cnt + (s->lim - s->bot));
|
||||
}
|
||||
else if (next == '\r')
|
||||
{
|
||||
int next2 = get_one_char(s);
|
||||
if (next2 == '\n')
|
||||
{
|
||||
--cnt; /* skip the backslash */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* rewind one, and skip one char */
|
||||
rewind_stream(s, -1);
|
||||
--cnt;
|
||||
}
|
||||
boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
|
||||
cnt + (s->lim - s->bot));
|
||||
}
|
||||
else if (next != -1) /* -1 means end of file */
|
||||
{
|
||||
/* next was something else, so rewind the stream */
|
||||
lseek(s->fd, -1, SEEK_CUR);
|
||||
}
|
||||
}
|
||||
/* check \ \r EOB */
|
||||
else if (last == '\r' && last2 == '\\')
|
||||
{
|
||||
int next = get_one_char(s);
|
||||
if (next == '\n')
|
||||
{
|
||||
cnt -= 2; /* skip the \ \r */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* rewind one, and skip two chars */
|
||||
rewind_stream(s, -1);
|
||||
cnt -= 2;
|
||||
}
|
||||
boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
|
||||
cnt + (s->lim - s->bot));
|
||||
}
|
||||
/* check \ \n EOB */
|
||||
else if (last == '\n' && last2 == '\\')
|
||||
{
|
||||
cnt -= 2;
|
||||
boost::wave::cpplexer::re2clex::aq_enqueue(s->eol_offsets,
|
||||
cnt + (s->lim - s->bot));
|
||||
}
|
||||
}
|
||||
|
||||
s->lim += cnt;
|
||||
if (s->eof) /* eof needs adjusting if we erased backslash-newlines */
|
||||
{
|
||||
s->eof = s->lim;
|
||||
*(s->eof)++ = '\0';
|
||||
}
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
boost::wave::token_id
|
||||
scan(boost::wave::cpplexer::re2clex::Scanner *s)
|
||||
{
|
||||
using namespace boost::wave::cpplexer::re2clex;
|
||||
|
||||
uchar *cursor = s->tok = s->cur;
|
||||
|
||||
/*!re2c
|
||||
any = [\t\v\f\r\n\040-\377];
|
||||
OctalDigit = [0-7];
|
||||
Digit = [0-9];
|
||||
HexDigit = [a-fA-F0-9];
|
||||
ExponentPart = [Ee] [+-]? Digit+;
|
||||
FractionalConstant = (Digit* "." Digit+) | (Digit+ ".");
|
||||
FloatingSuffix = [fF][lL]?|[lL][fF]?;
|
||||
IntegerSuffix = [uU][lL]?|[lL][uU]?;
|
||||
FixedPointSuffix = [dD];
|
||||
Backslash = [\\]|"??/";
|
||||
EscapeSequence = Backslash ([abfnrtv?'"] | Backslash | "x" HexDigit+ | OctalDigit OctalDigit? OctalDigit?);
|
||||
HexQuad = HexDigit HexDigit HexDigit HexDigit;
|
||||
UniversalChar = Backslash ("u" HexQuad | "U" HexQuad HexQuad);
|
||||
PPSpace = ([ \t]|("/*"((any\[*\n\r])*|"*"+(any\[*/\n\r])*|"\n"|"\r"|"\r\n")*"*/"))*;
|
||||
Pound = "#" | "??=" | "%:";
|
||||
Newline = "\r\n" | "\n" | "\r";
|
||||
*/
|
||||
|
||||
/*!re2c
|
||||
"/*" { goto ccomment; }
|
||||
"//" { goto cppcomment; }
|
||||
|
||||
"TRUE" { RET(T_TRUE); }
|
||||
"FALSE" { RET(T_FALSE); }
|
||||
|
||||
"{" { RET(T_LEFTBRACE); }
|
||||
"}" { RET(T_RIGHTBRACE); }
|
||||
"[" { RET(T_LEFTBRACKET); }
|
||||
"]" { RET(T_RIGHTBRACKET); }
|
||||
"#" { RET(T_POUND); }
|
||||
"##" { RET(T_POUND_POUND); }
|
||||
"(" { RET(T_LEFTPAREN); }
|
||||
")" { RET(T_RIGHTPAREN); }
|
||||
";" { RET(T_SEMICOLON); }
|
||||
":" { RET(T_COLON); }
|
||||
"?" { RET(T_QUESTION_MARK); }
|
||||
"." { RET(T_DOT); }
|
||||
"+" { RET(T_PLUS); }
|
||||
"-" { RET(T_MINUS); }
|
||||
"*" { RET(T_STAR); }
|
||||
"/" { RET(T_DIVIDE); }
|
||||
"%" { RET(T_PERCENT); }
|
||||
"^" { RET(T_XOR); }
|
||||
"&" { RET(T_AND); }
|
||||
"|" { RET(T_OR); }
|
||||
"~" { RET(T_COMPL); }
|
||||
"!" { RET(T_NOT); }
|
||||
"=" { RET(T_ASSIGN); }
|
||||
"<" { RET(T_LESS); }
|
||||
">" { RET(T_GREATER); }
|
||||
"<<" { RET(T_SHIFTLEFT); }
|
||||
">>" { RET(T_SHIFTRIGHT); }
|
||||
"==" { RET(T_EQUAL); }
|
||||
"!=" { RET(T_NOTEQUAL); }
|
||||
"<=" { RET(T_LESSEQUAL); }
|
||||
">=" { RET(T_GREATEREQUAL); }
|
||||
"&&" { RET(T_ANDAND); }
|
||||
"||" { RET(T_OROR); }
|
||||
"++" { RET(T_PLUSPLUS); }
|
||||
"--" { RET(T_MINUSMINUS); }
|
||||
"," { RET(T_COMMA); }
|
||||
|
||||
([a-zA-Z_] | UniversalChar) ([a-zA-Z_0-9] | UniversalChar)*
|
||||
{ RET(T_IDENTIFIER); }
|
||||
|
||||
(("0" [xX] HexDigit+) | ("0" OctalDigit*) | ([1-9] Digit*)) IntegerSuffix?
|
||||
{ RET(T_INTLIT); }
|
||||
|
||||
((FractionalConstant ExponentPart?) | (Digit+ ExponentPart)) FloatingSuffix?
|
||||
{ RET(T_FLOATLIT); }
|
||||
|
||||
(FractionalConstant | Digit+) FixedPointSuffix
|
||||
{ RET(T_FIXEDPOINTLIT); }
|
||||
|
||||
"L"? (['] (EscapeSequence|any\[\n\r\\']|UniversalChar)+ ['])
|
||||
{ RET(T_CHARLIT); }
|
||||
|
||||
"L"? (["] (EscapeSequence|any\[\n\r\\"]|UniversalChar)* ["])
|
||||
{ RET(T_STRINGLIT); }
|
||||
|
||||
|
||||
Pound PPSpace "include" PPSpace "<" (any\[\n\r>])+ ">"
|
||||
{ RET(T_PP_HHEADER); }
|
||||
|
||||
Pound PPSpace "include" PPSpace "\"" (any\[\n\r"])+ "\""
|
||||
{ RET(T_PP_QHEADER); }
|
||||
|
||||
Pound PPSpace "include" PPSpace
|
||||
{ RET(T_PP_INCLUDE); }
|
||||
|
||||
Pound PPSpace "if" { RET(T_PP_IF); }
|
||||
Pound PPSpace "ifdef" { RET(T_PP_IFDEF); }
|
||||
Pound PPSpace "ifndef" { RET(T_PP_IFNDEF); }
|
||||
Pound PPSpace "else" { RET(T_PP_ELSE); }
|
||||
Pound PPSpace "elif" { RET(T_PP_ELIF); }
|
||||
Pound PPSpace "endif" { RET(T_PP_ENDIF); }
|
||||
Pound PPSpace "define" { RET(T_PP_DEFINE); }
|
||||
Pound PPSpace "undef" { RET(T_PP_UNDEF); }
|
||||
Pound PPSpace "line" { RET(T_PP_LINE); }
|
||||
Pound PPSpace "error" { RET(T_PP_ERROR); }
|
||||
Pound PPSpace "pragma" { RET(T_PP_PRAGMA); }
|
||||
|
||||
Pound PPSpace "warning" { RET(T_PP_WARNING); }
|
||||
|
||||
[ \t\v\f]+
|
||||
{ RET(T_SPACE); }
|
||||
|
||||
Newline
|
||||
{
|
||||
s->line++;
|
||||
RET(T_NEWLINE);
|
||||
}
|
||||
|
||||
"\000"
|
||||
{
|
||||
if(cursor != s->eof)
|
||||
{
|
||||
if (0 != s->error_proc)
|
||||
(*s->error_proc)(s, "'\\000' in input stream");
|
||||
else
|
||||
printf("Error: 0 in file\n");
|
||||
}
|
||||
RET(T_EOF);
|
||||
}
|
||||
|
||||
any
|
||||
{
|
||||
/* if (0 != s->error_proc)
|
||||
(*s->error_proc)(s, "Unexpected character: '%c'", *s->tok);
|
||||
else
|
||||
printf("unexpected character: '%c'\n", *s->tok);
|
||||
*/
|
||||
RET(TOKEN_FROM_ID(*s->tok, UnknownTokenType));
|
||||
}
|
||||
*/
|
||||
|
||||
ccomment:
|
||||
/*!re2c
|
||||
"*/" { RET(T_CCOMMENT); }
|
||||
Newline
|
||||
{
|
||||
/*if(cursor == s->eof) RET(T_EOF);*/
|
||||
/*s->tok = cursor; */
|
||||
s->line += count_backslash_newlines(s, cursor) +1;
|
||||
goto ccomment;
|
||||
}
|
||||
|
||||
any { goto ccomment; }
|
||||
|
||||
"\000"
|
||||
{
|
||||
yyaccept = 0; /* avoid warning about unreferenced variable */
|
||||
if(cursor == s->eof)
|
||||
{
|
||||
if (s->error_proc)
|
||||
(*s->error_proc)(s, "Unterminated comment");
|
||||
else
|
||||
printf("Error: Unterminated comment\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->error_proc)
|
||||
(*s->error_proc)(s, "'\\000' in input stream");
|
||||
else
|
||||
printf("Error: 0 in file");
|
||||
}
|
||||
RET(T_EOF);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
cppcomment:
|
||||
/*!re2c
|
||||
Newline
|
||||
{
|
||||
/*if(cursor == s->eof) RET(T_EOF); */
|
||||
/*s->tok = cursor; */
|
||||
s->line++;
|
||||
RET(T_CPPCOMMENT);
|
||||
}
|
||||
|
||||
any { goto cppcomment; }
|
||||
|
||||
"\000"
|
||||
{
|
||||
yyaccept = 0; /* avoid warning about unreferenced variable */
|
||||
if(cursor != s->eof)
|
||||
{
|
||||
if (s->error_proc)
|
||||
(*s->error_proc)(s, "'\\000' in input stream");
|
||||
else
|
||||
printf("Error: 0 in file");
|
||||
}
|
||||
/* adjust cursor such next call returns T_EOF */
|
||||
--YYCURSOR;
|
||||
/* the comment is unterminated, but nevertheless its a comment */
|
||||
RET(T_CPPCOMMENT);
|
||||
}
|
||||
*/
|
||||
|
||||
} /* end of scan */
|
||||
|
||||
#undef RE2C_ASSERT
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace re2clex
|
||||
} // namespace idllexer
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
17072
samples/waveidl/idllexer/idl.re.cpp
Normal file
17072
samples/waveidl/idllexer/idl.re.cpp
Normal file
File diff suppressed because it is too large
Load Diff
36
samples/waveidl/idllexer/idl.re.hpp
Normal file
36
samples/waveidl/idllexer/idl.re.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: Re2C based IDL lexer
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(IDL_RE_HPP_BD62775D_1659_4684_872C_03C02543C9A5_INCLUDED)
|
||||
#define IDL_RE_HPP_BD62775D_1659_4684_872C_03C02543C9A5_INCLUDED
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace idllexer {
|
||||
namespace re2clex {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The scanner function to call whenever a new token is requested
|
||||
boost::wave::token_id scan(
|
||||
boost::wave::cpplexer::re2clex::Scanner *s);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace re2clex
|
||||
} // namespace idllexer
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(IDL_RE_HPP_BD62775D_1659_4684_872C_03C02543C9A5_INCLUDED)
|
||||
84
samples/waveidl/idllexer/idl_lex_interface.hpp
Normal file
84
samples/waveidl/idllexer/idl_lex_interface.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Definition of the abstract lexer interface
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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_LEX_INTERFACE_HPP_E83F52A4_90AC_4FBE_A9A7_B65F7F94C497_INCLUDED)
|
||||
#define CPP_LEX_INTERFACE_HPP_E83F52A4_90AC_4FBE_A9A7_B65F7F94C497_INCLUDED
|
||||
|
||||
#include <boost/wave/util/file_position.hpp>
|
||||
#include <boost/wave/language_support.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace idllexer {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// new_lexer_gen: generates a new instance of the required C++ lexer
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename TokenT> struct lex_input_interface;
|
||||
|
||||
template <
|
||||
typename IteratorT,
|
||||
typename PositionT = boost::wave::util::file_position_t
|
||||
>
|
||||
struct new_lexer_gen
|
||||
{
|
||||
// The NewLexer function allows the opaque generation of a new lexer object.
|
||||
// It is coupled to the token type to allow to decouple the lexer/token
|
||||
// configurations at compile time.
|
||||
static lex_input_interface<
|
||||
boost::wave::cpplexer::lex_token<PositionT>
|
||||
> *
|
||||
new_lexer(IteratorT const &first, IteratorT const &last,
|
||||
PositionT const &pos, boost::wave::language_support language);
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The lex_input_interface decouples the lex_iterator_shim from the actual
|
||||
// lexer. This is done to allow compile time reduction.
|
||||
// Thanks to JCAB for having this idea.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename TokenT>
|
||||
struct lex_input_interface
|
||||
{
|
||||
typedef typename TokenT::position_t position_t;
|
||||
|
||||
virtual TokenT get() = 0;
|
||||
virtual void set_position(position_t const &pos) = 0;
|
||||
|
||||
virtual ~lex_input_interface() {}
|
||||
|
||||
// The new_lexer function allows the opaque generation of a new lexer object.
|
||||
// It is coupled to the token type to allow to distinguish different
|
||||
// lexer/token configurations at compile time.
|
||||
template <typename IteratorT>
|
||||
static lex_input_interface *
|
||||
new_lexer(IteratorT const &first, IteratorT const &last,
|
||||
position_t const &pos, boost::wave::language_support language)
|
||||
{
|
||||
return new_lexer_gen<IteratorT, position_t>::new_lexer (first, last,
|
||||
pos, language);
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace cpplexer
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(CPP_LEX_INTERFACE_HPP_E83F52A4_90AC_4FBE_A9A7_B65F7F94C497_INCLUDED)
|
||||
137
samples/waveidl/idllexer/idl_lex_iterator.hpp
Normal file
137
samples/waveidl/idllexer/idl_lex_iterator.hpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: Re2C based IDL lexer
|
||||
Definition of the lexer iterator
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(IDL_LEX_ITERATOR_HPP_7926F865_E02F_4950_9EB5_5F453C9FF953_INCLUDED)
|
||||
#define IDL_LEX_ITERATOR_HPP_7926F865_E02F_4950_9EB5_5F453C9FF953_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/spirit/iterator/multi_pass.hpp>
|
||||
|
||||
#include <boost/wave/language_support.hpp>
|
||||
#include <boost/wave/util/file_position.hpp>
|
||||
#include <boost/wave/util/functor_input.hpp>
|
||||
|
||||
#include "idl_lex_interface.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace idllexer {
|
||||
namespace impl {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lex_iterator_functor_shim
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename TokenT>
|
||||
class lex_iterator_functor_shim
|
||||
{
|
||||
typedef lex_input_interface<TokenT> lex_input_interface_t;
|
||||
|
||||
public:
|
||||
template <typename IteratorT>
|
||||
lex_iterator_functor_shim(IteratorT const &first, IteratorT const &last,
|
||||
typename TokenT::position_t const &pos,
|
||||
boost::wave::language_support language)
|
||||
: functor_ptr(lex_input_interface_t::new_lexer(first, last, pos, language))
|
||||
{}
|
||||
|
||||
// interface to the boost::spirit::multi_pass_policies::functor_input policy
|
||||
typedef TokenT result_type;
|
||||
|
||||
static result_type const eof;
|
||||
|
||||
result_type operator()()
|
||||
{
|
||||
BOOST_ASSERT(0 != functor_ptr.get());
|
||||
return functor_ptr->get();
|
||||
}
|
||||
void set_position(typename TokenT::position_t const &pos)
|
||||
{
|
||||
BOOST_ASSERT(0 != functor_ptr.get());
|
||||
functor_ptr->set_position(pos);
|
||||
}
|
||||
|
||||
private:
|
||||
boost::shared_ptr<lex_input_interface_t> functor_ptr;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// eof token
|
||||
template <typename LexT>
|
||||
typename lex_iterator_functor_shim<LexT>::result_type const
|
||||
lex_iterator_functor_shim<LexT>::eof;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace impl
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lex_iterator
|
||||
//
|
||||
// A generic C++ lexer interface class, which allows to plug in different
|
||||
// lexer implementations (template parameter LexT). The following
|
||||
// requirement apply:
|
||||
//
|
||||
// - the lexer type should have a function implemented, which returnes
|
||||
// the next lexed token from the input stream:
|
||||
// typename LexT::token_t get();
|
||||
// - at the end of the input stream this function should return the
|
||||
// eof token equivalent
|
||||
// - the lexer should implement a constructor taking two iterators
|
||||
// pointing to the beginning and the end of the input stream and
|
||||
// a third parameter containing the name of the parsed input file
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename TokenT>
|
||||
class lex_iterator
|
||||
: public boost::spirit::multi_pass<
|
||||
impl::lex_iterator_functor_shim<TokenT>,
|
||||
boost::wave::util::functor_input
|
||||
>
|
||||
{
|
||||
typedef impl::lex_iterator_functor_shim<TokenT> input_policy_t;
|
||||
typedef
|
||||
boost::spirit::multi_pass<input_policy_t,
|
||||
boost::wave::util::functor_input>
|
||||
base_t;
|
||||
typedef lex_iterator<TokenT> self_t;
|
||||
|
||||
public:
|
||||
typedef TokenT token_t;
|
||||
|
||||
lex_iterator()
|
||||
{}
|
||||
|
||||
template <typename IteratorT>
|
||||
lex_iterator(IteratorT const &first, IteratorT const &last,
|
||||
typename TokenT::position_t const &pos,
|
||||
boost::wave::language_support language)
|
||||
: base_t(input_policy_t(first, last, pos, language))
|
||||
{}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace idllexer
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(IDL_LEX_ITERATOR_HPP_7926F865_E02F_4950_9EB5_5F453C9FF953_INCLUDED)
|
||||
264
samples/waveidl/idllexer/idl_re2c_lexer.hpp
Normal file
264
samples/waveidl/idllexer/idl_re2c_lexer.hpp
Normal file
@@ -0,0 +1,264 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Re2C based IDL lexer
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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(IDL_RE2C_LEXER_HPP_B81A2629_D5B1_4944_A97D_60254182B9A8_INCLUDED)
|
||||
#define IDL_RE2C_LEXER_HPP_B81A2629_D5B1_4944_A97D_60254182B9A8_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#if defined(BOOST_SPIRIT_DEBUG)
|
||||
#include <iostream>
|
||||
#endif // defined(BOOST_SPIRIT_DEBUG)
|
||||
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/spirit/core.hpp>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/language_support.hpp>
|
||||
#include <boost/wave/util/file_position.hpp>
|
||||
#include <boost/wave/cpplexer/validate_universal_char.hpp>
|
||||
#include <boost/wave/cpplexer/cpplexer_exceptions.hpp>
|
||||
|
||||
// reuse the default token type and re2c lexer helpers
|
||||
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
|
||||
#include <boost/wave/cpplexer/cpp_lex_interface.hpp>
|
||||
#include <boost/wave/cpplexer/re2clex/scanner.hpp>
|
||||
|
||||
#include "idl.re.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
namespace boost {
|
||||
namespace wave {
|
||||
namespace idllexer {
|
||||
namespace re2clex {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// encapsulation of the re2c based idl lexer
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <
|
||||
typename IteratorT,
|
||||
typename PositionT = boost::wave::util::file_position_t
|
||||
>
|
||||
class lexer
|
||||
{
|
||||
typedef boost::wave::cpplexer::re2clex::Scanner scanner_t;
|
||||
|
||||
public:
|
||||
|
||||
typedef char char_t;
|
||||
typedef boost::wave::cpplexer::re2clex::Scanner base_t;
|
||||
typedef boost::wave::cpplexer::lex_token<PositionT> token_t;
|
||||
typedef typename token_t::string_t string_t;
|
||||
|
||||
lexer(IteratorT const &first, IteratorT const &last,
|
||||
PositionT const &pos, boost::wave::language_support language);
|
||||
~lexer();
|
||||
|
||||
boost::wave::cpplexer::lex_token<PositionT> get();
|
||||
void set_position(PositionT const &pos)
|
||||
{
|
||||
filename = pos.get_file();
|
||||
scanner.line = pos.get_line();
|
||||
scanner.file_name = filename.c_str();
|
||||
}
|
||||
|
||||
// error reporting from the re2c generated lexer
|
||||
static int report_error(scanner_t *s, char *, ...);
|
||||
|
||||
private:
|
||||
static char const *tok_names[];
|
||||
|
||||
scanner_t scanner;
|
||||
string_t filename;
|
||||
bool at_eof;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// initialize cpp lexer
|
||||
template <typename IteratorT, typename PositionT>
|
||||
inline
|
||||
lexer<IteratorT, PositionT>::lexer(IteratorT const &first,
|
||||
IteratorT const &last, PositionT const &pos,
|
||||
boost::wave::language_support language)
|
||||
: filename(pos.get_file()), at_eof(false)
|
||||
{
|
||||
using namespace boost::wave::cpplexer::re2clex;
|
||||
|
||||
memset(&scanner, '\0', sizeof(scanner_t));
|
||||
scanner.fd = -1;
|
||||
scanner.eol_offsets = aq_create();
|
||||
scanner.first = scanner.act = (uchar *)&(*first);
|
||||
scanner.last = (uchar *)&(*last);
|
||||
scanner.line = 1; // start with line_no 1
|
||||
scanner.error_proc = report_error;
|
||||
scanner.file_name = filename.c_str();
|
||||
|
||||
// not used by the lexer
|
||||
scanner.enable_ms_extensions = 0;
|
||||
scanner.act_in_c99_mode = 0;
|
||||
scanner.act_in_cpp0x_mode = 0;
|
||||
|
||||
boost::ignore_unused_variable_warning(language);
|
||||
}
|
||||
|
||||
template <typename IteratorT, typename PositionT>
|
||||
inline
|
||||
lexer<IteratorT, PositionT>::~lexer()
|
||||
{
|
||||
boost::wave::cpplexer::re2clex::aq_terminate(scanner.eol_offsets);
|
||||
free(scanner.bot);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// get the next token from the input stream
|
||||
template <typename IteratorT, typename PositionT>
|
||||
inline boost::wave::cpplexer::lex_token<PositionT>
|
||||
lexer<IteratorT, PositionT>::get()
|
||||
{
|
||||
using namespace boost::wave; // to import token ids to this scope
|
||||
|
||||
if (at_eof)
|
||||
return boost::wave::cpplexer::lex_token<PositionT>(); // return T_EOI
|
||||
|
||||
token_id id = token_id(scan(&scanner));
|
||||
string_t value((char const *)scanner.tok, scanner.cur-scanner.tok);
|
||||
|
||||
if (T_IDENTIFIER == id) {
|
||||
// test identifier characters for validity (throws if invalid chars found)
|
||||
boost::wave::cpplexer::impl::validate_identifier_name(value,
|
||||
scanner.line, -1, filename);
|
||||
}
|
||||
else if (T_STRINGLIT == id || T_CHARLIT == id) {
|
||||
// test literal characters for validity (throws if invalid chars found)
|
||||
boost::wave::cpplexer::impl::validate_literal(value, scanner.line, -1,
|
||||
filename);
|
||||
}
|
||||
else if (T_EOF == id) {
|
||||
// T_EOF is returned as a valid token, the next call will return T_EOI,
|
||||
// i.e. the actual end of input
|
||||
at_eof = true;
|
||||
}
|
||||
return boost::wave::cpplexer::lex_token<PositionT>(id, value,
|
||||
PositionT(filename, scanner.line, -1));
|
||||
}
|
||||
|
||||
template <typename IteratorT, typename PositionT>
|
||||
inline int
|
||||
lexer<IteratorT, PositionT>::report_error(scanner_t *s, char *msg, ...)
|
||||
{
|
||||
BOOST_ASSERT(0 != s);
|
||||
BOOST_ASSERT(0 != msg);
|
||||
|
||||
using namespace std; // some system have vsprintf in namespace std
|
||||
|
||||
char buffer[200]; // should be large enough
|
||||
va_list params;
|
||||
va_start(params, msg);
|
||||
vsprintf(buffer, msg, params);
|
||||
va_end(params);
|
||||
|
||||
BOOST_WAVE_LEXER_THROW(boost::wave::cpplexer::lexing_exception,
|
||||
generic_lexing_error, buffer, s->line, -1, s->file_name);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// lex_functor
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <
|
||||
typename IteratorT,
|
||||
typename PositionT = boost::wave::util::file_position_t
|
||||
>
|
||||
class lex_functor
|
||||
: public lex_input_interface<typename lexer<IteratorT, PositionT>::token_t>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename lexer<IteratorT, PositionT>::token_t token_t;
|
||||
|
||||
lex_functor(IteratorT const &first, IteratorT const &last,
|
||||
PositionT const &pos, boost::wave::language_support language)
|
||||
: lexer(first, last, pos, language)
|
||||
{}
|
||||
virtual ~lex_functor() {}
|
||||
|
||||
// get the next token from the input stream
|
||||
token_t get() { return lexer.get(); }
|
||||
void set_position(PositionT const &pos)
|
||||
{ lexer.set_position(pos); }
|
||||
|
||||
private:
|
||||
lexer<IteratorT, PositionT> lexer;
|
||||
};
|
||||
|
||||
} // namespace re2clex
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The new_lexer_gen<>::new_lexer function (declared in cpp_slex_token.hpp)
|
||||
// should be defined inline, if the lex_functor shouldn't be instantiated
|
||||
// separately from the lex_iterator.
|
||||
//
|
||||
// Separate (explicit) instantiation helps to reduce compilation time.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION != 0
|
||||
#define BOOST_WAVE_RE2C_NEW_LEXER_INLINE
|
||||
#else
|
||||
#define BOOST_WAVE_RE2C_NEW_LEXER_INLINE inline
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// The 'new_lexer' function allows the opaque generation of a new lexer object.
|
||||
// It is coupled to the iterator type to allow to decouple the lexer/iterator
|
||||
// configurations at compile time.
|
||||
//
|
||||
// This function is declared inside the cpp_slex_token.hpp file, which is
|
||||
// referenced by the source file calling the lexer and the source file, which
|
||||
// instantiates the lex_functor. But is is defined here, so it will be
|
||||
// instantiated only while compiling the source file, which instantiates the
|
||||
// lex_functor. While the cpp_re2c_token.hpp file may be included everywhere,
|
||||
// this file (cpp_re2c_lexer.hpp) should be included only once. This allows
|
||||
// to decouple the lexer interface from the lexer implementation and reduces
|
||||
// compilation time.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename IteratorT, typename PositionT>
|
||||
BOOST_WAVE_RE2C_NEW_LEXER_INLINE
|
||||
lex_input_interface<boost::wave::cpplexer::lex_token<PositionT> > *
|
||||
new_lexer_gen<IteratorT, PositionT>::new_lexer(IteratorT const &first,
|
||||
IteratorT const &last, PositionT const &pos,
|
||||
wave::language_support language)
|
||||
{
|
||||
return new re2clex::lex_functor<IteratorT, PositionT>(first, last, pos,
|
||||
language);
|
||||
}
|
||||
|
||||
#undef BOOST_WAVE_RE2C_NEW_LEXER_INLINE
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace idllexer
|
||||
} // namespace wave
|
||||
} // namespace boost
|
||||
|
||||
#endif // !defined(IDL_RE2C_LEXER_HPP_B81A2629_D5B1_4944_A97D_60254182B9A8_INCLUDED)
|
||||
43
samples/waveidl/instantiate_cpp_grammar.cpp
Normal file
43
samples/waveidl/instantiate_cpp_grammar.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
Explicit instantiation of the cpp_grammar template
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "idl.hpp"
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
|
||||
|
||||
#include "idllexer/idl_lex_iterator.hpp"
|
||||
|
||||
#include <boost/wave/grammars/cpp_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Explicit instantiation of the cpp_grammar_gen template with the correct
|
||||
// token type. This instantiates the corresponding pt_parse function, which
|
||||
// in turn instantiates the cpp_grammar object
|
||||
// (see wave/grammars/cpp_grammar.hpp)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boost::wave::idllexer::lex_iterator<
|
||||
boost::wave::cpplexer::lex_token<> >
|
||||
lex_t;
|
||||
template struct boost::wave::grammars::cpp_grammar_gen<lex_t>;
|
||||
|
||||
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
43
samples/waveidl/instantiate_defined_grammar.cpp
Normal file
43
samples/waveidl/instantiate_defined_grammar.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
Explicit instantiation of the defined_grammar template
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "idl.hpp"
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
|
||||
|
||||
#include "idllexer/idl_lex_iterator.hpp"
|
||||
|
||||
#include <boost/wave/grammars/cpp_defined_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Explicit instantiation of the defined_grammar_gen template
|
||||
// with the correct token type. This instantiates the corresponding parse
|
||||
// function, which in turn instantiates the defined_grammar
|
||||
// object (see wave/grammars/cpp_defined_grammar.hpp)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boost::wave::idllexer::lex_iterator<
|
||||
boost::wave::cpplexer::lex_token<> >
|
||||
lex_t;
|
||||
template struct boost::wave::grammars::defined_grammar_gen<lex_t>;
|
||||
|
||||
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
43
samples/waveidl/instantiate_predef_macros.cpp
Normal file
43
samples/waveidl/instantiate_predef_macros.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
Explicit instantiation of the predefined_macros_grammar template
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "idl.hpp"
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
|
||||
|
||||
#include "idllexer/idl_lex_iterator.hpp"
|
||||
|
||||
#include <boost/wave/grammars/cpp_predef_macros_grammar.hpp>
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Explicit instantiation of the predefined_macros_grammar_gen template
|
||||
// with the correct token type. This instantiates the corresponding pt_parse
|
||||
// function, which in turn instantiates the cpp_predefined_macros_grammar
|
||||
// object (see wave/grammars/cpp_predef_macros_grammar.hpp)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef boost::wave::idllexer::lex_iterator<
|
||||
boost::wave::cpplexer::lex_token<> >
|
||||
lex_t;
|
||||
template struct boost::wave::grammars::predefined_macros_grammar_gen<lex_t>;
|
||||
|
||||
#endif // #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
|
||||
|
||||
51
samples/waveidl/instantiate_re2c_lexer.cpp
Normal file
51
samples/waveidl/instantiate_re2c_lexer.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
Explicit instantiation of the lex_functor generation function
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "idl.hpp"
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
|
||||
|
||||
#include "idllexer/idl_lex_iterator.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The following file needs to be included only once throughout the whole
|
||||
// program.
|
||||
#include "idllexer/idl_re2c_lexer.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This instantiates the correct 'new_lexer' function, which generates the
|
||||
// C++ lexer used in this sample. You will have to instantiate the
|
||||
// new_lexer_gen<> template with the same iterator type, as you have used for
|
||||
// instantiating the boost::wave::context<> object.
|
||||
//
|
||||
// This is moved into a separate compilation unit to decouple the compilation
|
||||
// of the C++ lexer from the compilation of the other modules, which helps to
|
||||
// reduce compilation time.
|
||||
//
|
||||
// The template parameter(s) supplied should be identical to the first
|
||||
// parameter supplied while instantiating the boost::wave::context<> template
|
||||
// (see the file cpp.cpp).
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template struct boost::wave::idllexer::new_lexer_gen<
|
||||
BOOST_WAVE_STRINGTYPE::iterator>;
|
||||
|
||||
#endif // BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION != 0
|
||||
51
samples/waveidl/instantiate_re2c_lexer_string.cpp
Normal file
51
samples/waveidl/instantiate_re2c_lexer_string.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*=============================================================================
|
||||
Wave: A Standard compliant C++ preprocessor library
|
||||
|
||||
Sample: IDL oriented preprocessor
|
||||
Explicit instantiation of the lex_functor generation function
|
||||
|
||||
Copyright (c) 2001-2004 Hartmut Kaiser
|
||||
http://spirit.sourceforge.net/
|
||||
|
||||
Use, modification and distribution is subject to 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)
|
||||
=============================================================================*/
|
||||
|
||||
#include "idl.hpp"
|
||||
|
||||
#if BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION != 0
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <boost/wave/token_ids.hpp>
|
||||
#include <boost/wave/cpplexer/cpp_lex_token.hpp>
|
||||
|
||||
#include "idllexer/idl_lex_iterator.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The following file needs to be included only once throughout the whole
|
||||
// program.
|
||||
#include "idllexer/idl_re2c_lexer.hpp"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// If you've used another iterator type as std::string::iterator, you have to
|
||||
// instantiate the new_lexer_gen<> template for this iterator type too.
|
||||
// The reason is, that the library internally uses the new_lexer_gen<>
|
||||
// template with a std::string::iterator. (You just have to undefine the
|
||||
// following line.)
|
||||
//
|
||||
// This is moved into a separate compilation unit to decouple the compilation
|
||||
// of the C++ lexer from the compilation of the other modules, which helps to
|
||||
// reduce compilation time.
|
||||
//
|
||||
// The template parameter(s) supplied should be identical to the first
|
||||
// parameter supplied while instantiating the boost::wave::context<> template
|
||||
// (see the file cpp.cpp).
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template struct boost::wave::idllexer::new_lexer_gen<std::string::iterator>;
|
||||
|
||||
#endif // BOOST_WAVE_SEPARATE_LEXER_INSTANTIATION != 0
|
||||
Reference in New Issue
Block a user