/*============================================================================= Copyright (c) 2002-2003 Martin Wille 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) =============================================================================*/ /////////////////////////////////////////////////////////////////////////////// // vim:ts=4:sw=4:et // // Demonstrate regular expression parsers for match based text conversion // // This sample requires an installed version of the boost regex library // (http://www.boost.org) The sample was tested with boost V1.29.0 // // Note: - there is no error handling in this example // - this program isn't particularly useful // // This example shows one way build a kind of filter program. // It reads input from std::cin and uses a grammar and actions // to print out a modified version of the input. // // [ Martin Wille, 10/18/2002 ] // /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// // // The following header must be included, if regular expression support is // required for Spirit. // // The BOOST_SPIRIT_NO_REGEX_LIB PP constant should be defined, if you're using the // Boost.Regex library from one translation unit only. Otherwise you have to // link with the Boost.Regex library as defined in the related documentation // (see. http://www.boost.org). // /////////////////////////////////////////////////////////////////////////////// #define BOOST_SPIRIT_NO_REGEX_LIB #include using namespace BOOST_SPIRIT_CLASSIC_NS; using namespace std; namespace { long triple(long val) { return 3*val; } /////////////////////////////////////////////////////////////////////////// // // actions // struct emit_constant { emit_constant(string const &text) : msg(text) {} template void operator()(Iterator b, Iterator e) const { cout.rdbuf()->sputn(msg.data(), msg.size()); } private: string msg; }; void copy_unmodified(char letter) { cout.rdbuf()->sputc(letter); } struct emit_modified_subscript { emit_modified_subscript(boost::function const &f) : modifier(f) {} template void operator()(Iterator b, Iterator e) const { string tmp(b+1,e-1); long val = strtol(tmp.c_str(),0, 0); ostringstream os; os << modifier(val); tmp = os.str(); cout.rdbuf()->sputc('['); cout.rdbuf()->sputn(tmp.c_str(), tmp.size()); cout.rdbuf()->sputc(']'); } private: boost::function modifier; }; } /////////////////////////////////////////////////////////////////////////////// // The grammar 'conversion_grammar' serves as a working horse for match based // text conversion. It does the following: // // - converts the word "class" into the word "struct" // - multiplies any integer number enclosed in square brackets with 3 // - any other input is simply copied to the output struct conversion_grammar : grammar { template struct definition { typedef ScannerT scanner_t; definition(conversion_grammar const &) { static const char expr[] = "\\[\\d+\\]"; first = ( ///////////////////////////////////////////////////////////// // note that "fallback" is the last alternative here ! top = *(class2struct || subscript || fallback), ///////////////////////////////////////////////////////////// // replace any occurrence of "class" by "struct" class2struct = str_p("class") [emit_constant("struct")], ///////////////////////////////////////////////////////////// // if the input maches "[some_number]" // "some_number" is multiplied by 3 before printing subscript = regex_p(expr) [emit_modified_subscript(&triple)], ///////////////////////////////////////////////////////////// // if nothing else can be done with the input // then it will be printed without modifications fallback = anychar_p [©_unmodified] ); } rule const & start() { return first; } private: subrule<0> top; subrule<1> class2struct; subrule<2> subscript; subrule<3> fallback; rule first; }; }; int main() { // this would print "struct foo {}; foo bar[9];": // parse("class foo {}; foo bar[3];", conversion_grammar()); // Note: the regular expression parser contained in the // grammar requires a bidirectional iterator. Therefore, // we cannot use sdt::istreambuf_iterator as one would // do with other Spirit parsers. istreambuf_iterator input_iterator(cin); std::deque input(input_iterator, istreambuf_iterator()); parse(input.begin(), input.end(), conversion_grammar()); return 0; }