2
0
mirror of https://github.com/boostorg/spirit.git synced 2026-01-19 16:52:10 +00:00
Files
spirit/example/application/cpp/cpp.cpp
2003-01-31 11:11:39 +00:00

151 lines
4.9 KiB
C++

/*=============================================================================
A Standard compliant C++ preprocessor
Copyright (c) 2001-2003 Hartmut Kaiser
http://spirit.sourceforge.net/
Permission to copy, use, modify, sell and distribute this software
is granted provided this copyright notice appears in all copies.
This software is provided "as is" without express or implied
warranty, and with no claim as to its suitability for any purpose.
See Copyright.txt for full copyright notices and acknowledegments.
=============================================================================*/
#include "cpp.hpp" // global configuration
#include "cpplexer/cpp_token_ids.hpp"
#include "cpplexer/cpp_lex_iterator.hpp"
#include "cpp/cpp_context.hpp"
///////////////////////////////////////////////////////////////////////////////
// include lexer specifics, import lexer names
#if defined(USE_SLEX_CPP_LEXER)
// use the slex based C++ lexer
#include "cpplexer/slex/cpp_slex_token.hpp"
#if !defined(CPP_SEPARATE_LEXER_INSTANTIATION)
#include "cpplexer/slex/cpp_slex_lexer.hpp"
#endif // !defined(CPP_SEPARATE_LEXER_INSTANTIATION)
using namespace cpplexer::slex;
#elif defined(USE_RE2C_CPP_LEXER)
// use the re2c based C++ lexer
#include "cpplexer/re2clex/cpp_re2c_token.hpp"
#if !defined(CPP_SEPARATE_LEXER_INSTANTIATION)
#include "cpplexer/re2clex/cpp_re2c_lexer.hpp"
#endif // !defined(CPP_SEPARATE_LEXER_INSTANTIATION)
using namespace cpplexer::re2clex;
#endif
///////////////////////////////////////////////////////////////////////////////
// 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 file>" << endl;
return 1;
}
ifstream infile(argv[1]);
string teststr;
if (infile.is_open()) {
string line;
for (getline(infile, line); infile.good(); getline(infile, line)) {
teststr += line;
teststr += '\n';
}
}
else {
teststr = argv[1];
}
// The template lex_functor<> is defined in both namespaces: cpplexer::slex and
// cpplexer::re2clex. The 'using namespace' directive above tells the compiler,
// which of them to use.
typedef cpp::context<lex_token<std::string::iterator> > context_t;
// The C preprocessor iterator shouldn't be constructed directly. It is to be
// generated through a cpp::context<> object. This cpp: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 (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 {
while (first != last) {
// retrieve next token
current_token = *first;
// find token name
string tokenname (cpplexer::get_token_name(cpplexer::token_id(current_token)));
// output token info
cout << "matched token "
<< tokenname
<< "(#" << cpplexer::token_id(ID_FROM_TOKEN(current_token))
<< ") at " << current_token.get_position().file << " ("
<< current_token.get_position().line << "/"
<< current_token.get_position().column
<< "): >" << current_token.get_value() << "<"
<< endl;
++first;
}
}
catch (cpp::abort_preprocess_exception &e) {
// abort the preprocessing: simply abort compilation
cerr
<< e.file_name() << "(" << e.line_no() << "): "
<< "aborting preprocessing."
<< endl;
return 1;
}
catch (cpp::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().file
<< "(" << current_token.get_position().line << "): "
<< "unexpected exception: " << e.what()
<< endl;
return 3;
}
catch (...) {
// use last recognized token to retrieve the error position
cerr
<< current_token.get_position().file
<< "(" << current_token.get_position().line << "): "
<< "unexpected exception." << endl;
return 4;
}
return 0;
}