summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/spirit/classic/example/intermediate
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/spirit/classic/example/intermediate')
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/ipv4.cpp304
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/ipv4_opt.cpp213
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/lazy_parser.cpp126
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/parameters.cpp216
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/regex_convert.cpp177
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/simple_xml/actions.hpp68
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/simple_xml/driver.cpp43
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.cpp46
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.hpp33
-rw-r--r--src/boost/libs/spirit/classic/example/intermediate/simple_xml/xml_g.hpp186
10 files changed, 1412 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/classic/example/intermediate/ipv4.cpp b/src/boost/libs/spirit/classic/example/intermediate/ipv4.cpp
new file mode 100644
index 00000000..93453bac
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/ipv4.cpp
@@ -0,0 +1,304 @@
+/*=============================================================================
+ Copyright (c) 2002-2003 Joel de Guzman
+ 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 <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_push_back_actor.hpp>
+#include <boost/spirit/include/classic_if.hpp>
+#include <boost/spirit/include/classic_for.hpp>
+#include <boost/spirit/include/phoenix1.hpp>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Sample parser for binary data. This sample highlights the use of dynamic
+// parsing where the result of actions direct the actual parsing behavior.
+// We shall demonstrate 1) the use of phoenix to implement lambda (unnamed)
+// functions, 2) dynamic looping using for_p, 3) the push_back_a actor for
+// stuffing data into a vector, and 4) the if_p parser for choosing parser
+// branches based on semantic conditions.
+//
+// << Sample idea by Florian Weimer >>
+//
+// For simplicity, we shall use bytes as atoms (and not 16-bit quantities
+// in big-endian format or something similar, which would be more realistic)
+// and PASCAL strings.
+//
+// A packet is the literal octet with value 255, followed by a variable
+// octet N (denoting the total length of the packet), followed by N-2 octets
+// (the payload). The payload contains a variable-length header, followed
+// by zero or more elements.
+//
+// The header contains a single PASCAL string.
+//
+// An element is a PASCAL string (alternative: an element is an octet M,
+// followed by [M/8] bytes, i.e. the necessary number of bytes to store M
+// bits).
+//
+// (This data structure is inspired by the format of a BGP UPDATE message.)
+//
+// Packet layout:
+//
+// .-------------------.
+// | 0xff | ^
+// +-------------------+ |
+// | packet length | |
+// +-------------------+ | number of bytes indicated by packet length
+// : : |
+// : payload : |
+// | | v
+// `-------------------'
+//
+// Payload layout:
+//
+// .-------------------.
+// | header length |
+// +-------------------+
+// | header octets | ^
+// : : | number of octets given by header length
+// : : |
+// : : v
+// +-------------------+
+// | IPv4 prefix | ^
+// : : | IPv4 prefixes have variable length (see
+// +-------------------+ | below). The number of prefixes is
+// | IPv4 prefix | | determined by the packet length.
+// : : |
+// +-------------------+ |
+// : : |
+// : : v
+//
+//
+// IPv4 prefix layout comes in five variants, depending on the first
+// octet:
+//
+// .-------------------.
+// | 0x00 | single octet, corresponds to 0.0.0.0/0
+// `-------------------'
+//
+// .-------------------.
+// | 0x01 to 0x08 | two octets, prefix lengths up to /8.
+// +-------------------+
+// | MSB of network |
+// `-------------------'
+//
+// .-------------------.
+// | 0x09 to 0x10 | three octets, prefix lengths up to /16.
+// +-------------------+
+// | MSB of network |
+// +-------------------+
+// | next octet |
+// `-------------------'
+//
+// .-------------------.
+// | 0x11 to 0x18 | four octets, prefix lengths up to /24.
+// +-------------------+
+// | MSB of network |
+// +-------------------+
+// | next octet |
+// +-------------------+
+// | next octet |
+// `-------------------'
+//
+// .-------------------.
+// | 0x19 to 0x20 | five octets, prefix lengths up to /32.
+// +-------------------+
+// | MSB of network |
+// +-------------------+
+// | next octet |
+// +-------------------+
+// | next octet |
+// +-------------------+
+// | LSB of network |
+// `-------------------'
+//
+///////////////////////////////////////////////////////////////////////////////
+using namespace std;
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+using namespace phoenix;
+
+struct ipv4_prefix_data
+{
+ char prefix_len, n0, n1, n2, n3;
+
+ ipv4_prefix_data()
+ : prefix_len(0),n0(0),n1(0),n2(0),n3(0) {}
+};
+
+struct ipv4_data
+{
+ char packet_len, header_len;
+ std::string header;
+ std::vector<ipv4_prefix_data> prefixes;
+
+ ipv4_data()
+ : packet_len(0),header_len(0){}
+
+};
+
+struct ipv4 : public grammar<ipv4>
+{
+ template <typename ScannerT>
+ struct definition
+ {
+ definition(ipv4 const& self)
+ {
+ packet =
+ '\xff'
+ >> anychar_p[var(self.data.packet_len) = arg1]
+ >> payload
+ ;
+
+ payload =
+ anychar_p[var(self.data.header_len) = arg1]
+ >> for_p(var(i) = 0, var(i) < var(self.data.header_len), ++var(i))
+ [
+ anychar_p[var(self.data.header) += arg1]
+ ]
+ >> *ipv4_prefix
+ ;
+
+ ipv4_prefix =
+ anychar_p
+ [
+ var(temp.prefix_len) = arg1,
+ var(temp.n0) = 0,
+ var(temp.n1) = 0,
+ var(temp.n2) = 0,
+ var(temp.n3) = 0
+ ]
+
+ >> if_p(var(temp.prefix_len) > 0x00)
+ [
+ anychar_p[var(temp.n0) = arg1]
+ >> if_p(var(temp.prefix_len) > 0x08)
+ [
+ anychar_p[var(temp.n1) = arg1]
+ >> if_p(var(temp.prefix_len) > 0x10)
+ [
+ anychar_p[var(temp.n2) = arg1]
+ >> if_p(var(temp.prefix_len) > 0x18)
+ [
+ anychar_p[var(temp.n3) = arg1]
+ ]
+ ]
+ ]
+ ]
+ [
+ push_back_a(self.data.prefixes, temp)
+ ]
+ ;
+ }
+
+ int i;
+ ipv4_prefix_data temp;
+ rule<ScannerT> packet, payload, ipv4_prefix;
+ rule<ScannerT> const&
+ start() const { return packet; }
+ };
+
+ ipv4(ipv4_data& data)
+ : data(data) {}
+
+ ipv4_data& data;
+};
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Main program
+//
+////////////////////////////////////////////////////////////////////////////
+int
+as_byte(char n)
+{
+ if (n < 0)
+ return n + 256;
+ return n;
+}
+
+void
+print_prefix(ipv4_prefix_data const& prefix)
+{
+ cout << "prefix length = " << as_byte(prefix.prefix_len) << endl;
+ cout << "n0 = " << as_byte(prefix.n0) << endl;
+ cout << "n1 = " << as_byte(prefix.n1) << endl;
+ cout << "n2 = " << as_byte(prefix.n2) << endl;
+ cout << "n3 = " << as_byte(prefix.n3) << endl;
+}
+
+void
+parse_ipv4(char const* str, unsigned len)
+{
+ ipv4_data data;
+ ipv4 g(data);
+ parse_info<> info = parse(str, str+len, g);
+
+ if (info.full)
+ {
+ cout << "-------------------------\n";
+ cout << "Parsing succeeded\n";
+
+ cout << "packet length = " << as_byte(data.packet_len) << endl;
+ cout << "header length = " << as_byte(data.header_len) << endl;
+ cout << "header = " << data.header << endl;
+
+ for_each(data.prefixes.begin(), data.prefixes.end(), print_prefix);
+ cout << "-------------------------\n";
+ }
+ else
+ {
+ cout << "Parsing failed\n";
+ cout << "stopped at:";
+ for (char const* s = info.stop; s != str+len; ++s)
+ cout << static_cast<int>(*s) << endl;
+ }
+}
+
+// Test inputs:
+
+// The string in the header is "empty", the prefix list is empty.
+char const i1[8] =
+{
+ 0xff,0x08,0x05,
+ 'e','m','p','t','y'
+};
+
+// The string in the header is "default route", the prefix list
+// has just one element, 0.0.0.0/0.
+char const i2[17] =
+{
+ 0xff,0x11,0x0d,
+ 'd','e','f','a','u','l','t',' ',
+ 'r','o','u','t','e',
+ 0x00
+};
+
+// The string in the header is "private address space", the prefix list
+// has the elements 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.
+char const i3[32] =
+{
+ 0xff,0x20,0x15,
+ 'p','r','i','v','a','t','e',' ',
+ 'a','d','d','r','e','s','s',' ',
+ 's','p','a','c','e',
+ 0x08,0x0a,
+ 0x0c,0xac,0x10,
+ 0x10,0xc0,0xa8
+};
+
+int
+main()
+{
+ parse_ipv4(i1, sizeof(i1));
+ parse_ipv4(i2, sizeof(i2));
+ parse_ipv4(i3, sizeof(i3));
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/classic/example/intermediate/ipv4_opt.cpp b/src/boost/libs/spirit/classic/example/intermediate/ipv4_opt.cpp
new file mode 100644
index 00000000..ed5429fd
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/ipv4_opt.cpp
@@ -0,0 +1,213 @@
+/*=============================================================================
+ Copyright (c) 2002-2003 Joel de Guzman
+ 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 <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_push_back_actor.hpp>
+#include <boost/spirit/include/classic_if.hpp>
+#include <boost/spirit/include/classic_for.hpp>
+#include <boost/spirit/include/phoenix1.hpp>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Please check it out ipv4.cpp sample first!
+// << See ipv4.cpp sample for details >>
+//
+// This is a variation of the ipv4.cpp sample. The original ipv4.cpp code
+// compiles to 36k on MSVC7.1. Not bad! Yet, we want to shave a little bit
+// more. Is it possible? Yes! This time, we'll use subrules and just store
+// the rules in a plain old struct. We are parsing at the char level anyway,
+// so we know what type of rule we'll need: a plain rule<>. The result: we
+// shaved off another 20k. Now the code compiles to 16k on MSVC7.1.
+//
+// Could we have done better? Yes, but only if only we had typeof! << See
+// the techniques section of the User's guide >> ... Someday... :-)
+//
+///////////////////////////////////////////////////////////////////////////////
+using namespace std;
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+using namespace phoenix;
+
+struct ipv4_prefix_data
+{
+ char prefix_len, n0, n1, n2, n3;
+
+ ipv4_prefix_data()
+ : prefix_len(0),n0(0),n1(0),n2(0),n3(0) {}
+};
+
+struct ipv4_data
+{
+ char packet_len, header_len;
+ std::string header;
+ std::vector<ipv4_prefix_data> prefixes;
+
+ ipv4_data()
+ : packet_len(0),header_len(0){}
+
+};
+
+struct ipv4
+{
+ ipv4(ipv4_data& data)
+ : data(data)
+ {
+ start =
+ (
+ packet =
+ '\xff'
+ >> anychar_p[var(data.packet_len) = arg1]
+ >> payload
+ ,
+
+ payload =
+ anychar_p[var(data.header_len) = arg1]
+ >> for_p(var(i) = 0, var(i) < var(data.header_len), ++var(i))
+ [
+ anychar_p[var(data.header) += arg1]
+ ]
+ >> *ipv4_prefix
+ ,
+
+ ipv4_prefix =
+ anychar_p
+ [
+ var(temp.prefix_len) = arg1,
+ var(temp.n0) = 0,
+ var(temp.n1) = 0,
+ var(temp.n2) = 0,
+ var(temp.n3) = 0
+ ]
+
+ >> if_p(var(temp.prefix_len) > 0x00)
+ [
+ anychar_p[var(temp.n0) = arg1]
+ >> if_p(var(temp.prefix_len) > 0x08)
+ [
+ anychar_p[var(temp.n1) = arg1]
+ >> if_p(var(temp.prefix_len) > 0x10)
+ [
+ anychar_p[var(temp.n2) = arg1]
+ >> if_p(var(temp.prefix_len) > 0x18)
+ [
+ anychar_p[var(temp.n3) = arg1]
+ ]
+ ]
+ ]
+ ]
+ [
+ push_back_a(data.prefixes, temp)
+ ]
+ );
+ }
+
+ int i;
+ ipv4_prefix_data temp;
+
+ rule<> start;
+ subrule<0> packet;
+ subrule<1> payload;
+ subrule<2> ipv4_prefix;
+ ipv4_data& data;
+};
+
+////////////////////////////////////////////////////////////////////////////
+//
+// Main program
+//
+////////////////////////////////////////////////////////////////////////////
+int
+as_byte(char n)
+{
+ if (n < 0)
+ return n + 256;
+ return n;
+}
+
+void
+print_prefix(ipv4_prefix_data const& prefix)
+{
+ cout << "prefix length = " << as_byte(prefix.prefix_len) << endl;
+ cout << "n0 = " << as_byte(prefix.n0) << endl;
+ cout << "n1 = " << as_byte(prefix.n1) << endl;
+ cout << "n2 = " << as_byte(prefix.n2) << endl;
+ cout << "n3 = " << as_byte(prefix.n3) << endl;
+}
+
+void
+parse_ipv4(char const* str, unsigned len)
+{
+ ipv4_data data;
+ ipv4 g(data);
+ parse_info<> info = parse(str, str+len, g.start);
+
+ if (info.full)
+ {
+ cout << "-------------------------\n";
+ cout << "Parsing succeeded\n";
+
+ cout << "packet length = " << as_byte(data.packet_len) << endl;
+ cout << "header length = " << as_byte(data.header_len) << endl;
+ cout << "header = " << data.header << endl;
+
+ for_each(data.prefixes.begin(), data.prefixes.end(), print_prefix);
+ cout << "-------------------------\n";
+ }
+ else
+ {
+ cout << "Parsing failed\n";
+ cout << "stopped at:";
+ for (char const* s = info.stop; s != str+len; ++s)
+ cout << static_cast<int>(*s) << endl;
+ }
+}
+
+// Test inputs:
+
+// The string in the header is "empty", the prefix list is empty.
+char const i1[8] =
+{
+ 0xff,0x08,0x05,
+ 'e','m','p','t','y'
+};
+
+// The string in the header is "default route", the prefix list
+// has just one element, 0.0.0.0/0.
+char const i2[17] =
+{
+ 0xff,0x11,0x0d,
+ 'd','e','f','a','u','l','t',' ',
+ 'r','o','u','t','e',
+ 0x00
+};
+
+// The string in the header is "private address space", the prefix list
+// has the elements 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.
+char const i3[32] =
+{
+ 0xff,0x20,0x15,
+ 'p','r','i','v','a','t','e',' ',
+ 'a','d','d','r','e','s','s',' ',
+ 's','p','a','c','e',
+ 0x08,0x0a,
+ 0x0c,0xac,0x10,
+ 0x10,0xc0,0xa8
+};
+
+int
+main()
+{
+ parse_ipv4(i1, sizeof(i1));
+ parse_ipv4(i2, sizeof(i2));
+ parse_ipv4(i3, sizeof(i3));
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/classic/example/intermediate/lazy_parser.cpp b/src/boost/libs/spirit/classic/example/intermediate/lazy_parser.cpp
new file mode 100644
index 00000000..6035fd80
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/lazy_parser.cpp
@@ -0,0 +1,126 @@
+/*=============================================================================
+ Copyright (c) 2003 Vaclav Vesely
+ 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)
+=============================================================================*/
+//
+// This example demonstrates the lazy_p parser. You should read
+// "The Lazy Parser" in the documentation.
+//
+// We want to parse nested blocks of numbers like this:
+//
+// dec {
+// 1 2 3
+// bin {
+// 1 10 11
+// }
+// 4 5 6
+// }
+//
+// where the numbers in the "dec" block are wrote in the decimal system and
+// the numbers in the "bin" block are wrote in the binary system. We want
+// parser to return the overall sum.
+//
+// To achive this when base ("bin" or "dec") is parsed, in semantic action
+// we store a pointer to the appropriate numeric parser in the closure
+// variable block.int_rule. Than, when we need to parse a number we use lazy_p
+// parser to invoke the parser stored in the block.int_rule pointer.
+//
+//-----------------------------------------------------------------------------
+#include <boost/assert.hpp>
+#include <boost/cstdlib.hpp>
+#include <boost/spirit/include/phoenix1.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+#include <boost/spirit/include/classic_attribute.hpp>
+#include <boost/spirit/include/classic_dynamic.hpp>
+
+using namespace boost;
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+using namespace phoenix;
+
+//-----------------------------------------------------------------------------
+// my grammar
+
+struct my_grammar
+ : public grammar<my_grammar, parser_context<int> >
+{
+ // grammar definition
+ template<typename ScannerT>
+ struct definition
+ {
+ typedef rule<ScannerT> rule_t;
+ typedef stored_rule<ScannerT, parser_context<int> > number_rule_t;
+
+ struct block_closure;
+ typedef boost::spirit::classic::closure<
+ block_closure,
+ int,
+ typename number_rule_t::alias_t>
+ closure_base_t;
+
+ struct block_closure : closure_base_t
+ {
+ typename closure_base_t::member1 sum;
+ typename closure_base_t::member2 int_rule;
+ };
+
+ // block rule type
+ typedef rule<ScannerT, typename block_closure::context_t> block_rule_t;
+
+ block_rule_t block;
+ rule_t block_item;
+ symbols<number_rule_t> base;
+
+ definition(my_grammar const& self)
+ {
+ block =
+ base[
+ block.sum = 0,
+ // store a number rule in a closure member
+ block.int_rule = arg1
+ ]
+ >> "{"
+ >> *block_item
+ >> "}"
+ ;
+
+ block_item =
+ // use the stored rule
+ lazy_p(block.int_rule)[block.sum += arg1]
+ | block[block.sum += arg1]
+ ;
+
+ // bind base keywords and number parsers
+ base.add
+ ("bin", bin_p)
+ ("dec", uint_p)
+ ;
+ }
+
+ block_rule_t const& start() const
+ {
+ return block;
+ }
+ };
+};
+
+//-----------------------------------------------------------------------------
+
+int main()
+{
+ my_grammar gram;
+ parse_info<> info;
+
+ int result;
+ info = parse("bin{1 dec{1 2 3} 10}", gram[var(result) = arg1], space_p);
+ BOOST_ASSERT(info.full);
+ BOOST_ASSERT(result == 9);
+
+ return exit_success;
+}
+
+//-----------------------------------------------------------------------------
diff --git a/src/boost/libs/spirit/classic/example/intermediate/parameters.cpp b/src/boost/libs/spirit/classic/example/intermediate/parameters.cpp
new file mode 100644
index 00000000..b93fb0ec
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/parameters.cpp
@@ -0,0 +1,216 @@
+/*=============================================================================
+ Copyright (c) 2001-2003 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+// This sample show the usage of parser parameters.
+//
+// Parser parameters are used to pass some values from the outer parsing scope
+// to the next inner scope. They can be imagined as the opposite to the return
+// value paradigm, which returns some value from the inner to the next outer
+// scope. See the "Closures" chapter in the User's Guide.
+
+#include <string>
+#include <iostream>
+#include <cassert>
+
+#if defined(_MSC_VER) /*&& !defined(__COMO__)*/
+#pragma warning(disable: 4244)
+#pragma warning(disable: 4355)
+#endif // defined(_MSC_VER) && !defined(__COMO__)
+
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+#include <boost/spirit/include/classic_closure.hpp>
+
+#include <boost/spirit/include/phoenix1_tuples.hpp>
+#include <boost/spirit/include/phoenix1_tuple_helpers.hpp>
+#include <boost/spirit/include/phoenix1_primitives.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// used namespaces
+using namespace BOOST_SPIRIT_CLASSIC_NS;
+using namespace phoenix;
+using namespace std;
+
+///////////////////////////////////////////////////////////////////////////////
+// Helper class for encapsulation of the type for the parsed variable names
+class declaration_type
+{
+public:
+ enum vartype {
+ vartype_unknown = 0, // unknown variable type
+ vartype_int = 1, // 'int'
+ vartype_real = 2 // 'real'
+ };
+
+ declaration_type() : type(vartype_unknown)
+ {
+ }
+ template <typename ItT>
+ declaration_type(ItT const &first, ItT const &last)
+ {
+ init(string(first, last-first-1));
+ }
+ declaration_type(declaration_type const &type_) : type(type_.type)
+ {
+ }
+ declaration_type(string const &type_) : type(vartype_unknown)
+ {
+ init(type_);
+ }
+
+// access to the variable type
+ operator vartype const &() const { return type; }
+ operator string ()
+ {
+ switch(type) {
+ default:
+ case vartype_unknown: break;
+ case vartype_int: return string("int");
+ case vartype_real: return string("real");
+ }
+ return string ("unknown");
+ }
+
+ void swap(declaration_type &s) { std::swap(type, s.type); }
+
+protected:
+ void init (string const &type_)
+ {
+ if (type_ == "int")
+ type = vartype_int;
+ else if (type_ == "real")
+ type = vartype_real;
+ else
+ type = vartype_unknown;
+ }
+
+private:
+ vartype type;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// used closure type
+//
+///////////////////////////////////////////////////////////////////////////////
+struct var_decl_closure : BOOST_SPIRIT_CLASSIC_NS::closure<var_decl_closure, declaration_type>
+{
+ member1 val;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// symbols_with_data
+//
+// Helper class for inserting an item with data into a symbol table
+//
+///////////////////////////////////////////////////////////////////////////////
+template <typename T, typename InitT>
+class symbols_with_data
+{
+public:
+ typedef
+ symbol_inserter<T, BOOST_SPIRIT_CLASSIC_NS::impl::tst<T, char> >
+ symbol_inserter_t;
+
+ symbols_with_data(symbol_inserter_t const &add_, InitT const &data_) :
+ add(add_), data(as_actor<InitT>::convert(data_))
+ {
+ }
+
+ template <typename IteratorT>
+ symbol_inserter_t const &
+ operator()(IteratorT const &first_, IteratorT const &last) const
+ {
+ IteratorT first = first_;
+ return add(first, last, data());
+ }
+
+private:
+ symbol_inserter_t const &add;
+ typename as_actor<InitT>::type data;
+};
+
+template <typename T, typename CharT, typename InitT>
+inline
+symbols_with_data<T, InitT>
+symbols_gen(symbol_inserter<T, BOOST_SPIRIT_CLASSIC_NS::impl::tst<T, CharT> > const &add_,
+ InitT const &data_)
+{
+ return symbols_with_data<T, InitT>(add_, data_);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// The var_decl_list grammar parses variable declaration list
+
+struct var_decl_list :
+ public grammar<var_decl_list, var_decl_closure::context_t>
+{
+ template <typename ScannerT>
+ struct definition
+ {
+ definition(var_decl_list const &self)
+ {
+ // pass variable type returned from 'type' to list closure member 0
+ decl = type[self.val = arg1] >> +space_p >> list(self.val);
+
+ // m0 to access arg 0 of list --> passing variable type down to ident
+ list = ident(list.val) >> *(',' >> ident(list.val));
+
+ // store identifier and type into the symbol table
+ ident = (*alnum_p)[symbols_gen(symtab.add, ident.val)];
+
+ // the type of the decl is returned in type's closure member 0
+ type =
+ str_p("int")[type.val = construct_<string>(arg1, arg2)]
+ | str_p("real")[type.val = construct_<string>(arg1, arg2)]
+ ;
+
+ BOOST_SPIRIT_DEBUG_RULE(decl);
+ BOOST_SPIRIT_DEBUG_RULE(list);
+ BOOST_SPIRIT_DEBUG_RULE(ident);
+ BOOST_SPIRIT_DEBUG_RULE(type);
+ }
+
+ rule<ScannerT> const&
+ start() const { return decl; }
+
+ private:
+ typedef rule<ScannerT, var_decl_closure::context_t> rule_t;
+ rule_t type;
+ rule_t list;
+ rule_t ident;
+ symbols<declaration_type> symtab;
+
+ rule<ScannerT> decl; // start rule
+ };
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// main entry point
+int main()
+{
+var_decl_list decl;
+declaration_type type;
+char const *pbegin = "int var1";
+
+ if (parse (pbegin, decl[assign(type)]).full) {
+ cout << endl
+ << "Parsed variable declarations successfully!" << endl
+ << "Detected type: " << declaration_type::vartype(type)
+ << " (" << string(type) << ")"
+ << endl;
+ } else {
+ cout << endl
+ << "Parsing the input stream failed!"
+ << endl;
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/classic/example/intermediate/regex_convert.cpp b/src/boost/libs/spirit/classic/example/intermediate/regex_convert.cpp
new file mode 100644
index 00000000..e167c2e3
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/regex_convert.cpp
@@ -0,0 +1,177 @@
+/*=============================================================================
+ 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 <string>
+#include <iostream>
+#include <streambuf>
+#include <sstream>
+#include <deque>
+#include <iterator>
+
+#include <boost/function.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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 <boost/spirit/include/classic_regex.hpp>
+
+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<typename Iterator>
+ 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<long (long)> const &f)
+ : modifier(f)
+ {}
+
+ template<typename Iterator>
+ 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<long (long)> 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<conversion_grammar>
+{
+ template<class ScannerT>
+ 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 [&copy_unmodified]
+ );
+ }
+
+ rule<scanner_t> const & start() { return first; }
+
+ private:
+
+ subrule<0> top;
+ subrule<1> class2struct;
+ subrule<2> subscript;
+ subrule<3> fallback;
+ rule<scanner_t> 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<char> input_iterator(cin);
+ std::deque<char> input(input_iterator, istreambuf_iterator<char>());
+
+ parse(input.begin(), input.end(), conversion_grammar());
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/actions.hpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/actions.hpp
new file mode 100644
index 00000000..285edf21
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/actions.hpp
@@ -0,0 +1,68 @@
+// Copyright (c) 2005 Carl Barron. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef ACTIONS_H
+#define ACTIONS_H
+#include <boost/spirit/include/phoenix1.hpp>
+#include <boost/variant.hpp>
+#include "tag.hpp"
+
+struct push_child_impl
+{
+ template <class T,class A>
+ struct result {typedef void type;};
+
+ template <class T,class A>
+ void operator () (T &list, const A &value) const
+ {
+ typename tag::variant_type p(value);
+ list.push_back(p);
+ }
+};
+
+struct store_in_map_impl
+{
+ template <class T,class A>
+ struct result{typedef void type;};
+
+ template <class T,class A>
+ void operator () (T &map,const A &value)const
+ {
+ typedef typename T::value_type value_type;
+ map.insert(value_type(value));
+ }
+};
+
+struct push_back_impl
+{
+ template <class T,class A>
+ struct result {typedef void type;};
+
+ template <class T,class A>
+ void operator () (T &list,const A &value)const
+ {
+ list.push_back(value);
+ }
+};
+
+struct store_tag_impl
+{
+ template <class T,class A,class B,class C>
+ struct result {typedef void type;};
+
+ template <class T,class A,class B,class C>
+ void operator ()(T &t,const A &a,const B &b,const C &c)const
+ {
+ t.id = a;
+ t.attributes = b;
+ t.children = c;
+ }
+};
+
+
+typedef phoenix::function<push_back_impl> push_back_f;
+typedef phoenix::function<store_in_map_impl>store_in_map_f;
+typedef phoenix::function<push_child_impl> push_child_f;
+typedef phoenix::function<store_tag_impl> store_tag_f;
+#endif
diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/driver.cpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/driver.cpp
new file mode 100644
index 00000000..57ad6f20
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/driver.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2005 Carl Barron. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "xml_g.hpp"
+#include <boost/spirit/include/classic_utility.hpp>
+#include <iostream>
+
+namespace std
+{
+ std::ostream & operator << (std::ostream &os,std::pair<std::string,std::string> const &p)
+ {
+ return os << p.first << '=' << p.second;
+ }
+
+ std::ostream & operator << (std::ostream &os,const tag &t)
+ {
+ return os << t.id;
+ }
+
+}
+
+int main()
+{
+ const char *test =
+ // "<A x=\"1\" y=\"2\"> test 1 </A>"
+ // "<B x=\"3\" y= \"4\" z = \"10\"> test 3 </B>"
+ // "<C><A></A><V><W></W></V></C>"
+ // "<D x=\"4\"/>"
+ "<E>xxx<F>yyy</F>zzz</E>"
+ ;
+ std::list<tag> tags;
+ xml_g g(tags);
+
+ if(SP::parse(test,g,SP::comment_p("<---","--->")).full)
+ {
+ std::for_each(tags.begin(),tags.end(),walk_data());
+ }
+ else
+ {
+ std::cout << "parse failed\n";
+ }
+}
diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.cpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.cpp
new file mode 100644
index 00000000..088f3a00
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.cpp
@@ -0,0 +1,46 @@
+// Copyright (c) 2005 Carl Barron. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include "tag.hpp"
+#include <iostream>
+#include <algorithm>
+
+namespace
+{
+ struct print_pair
+ {
+ template <class P>
+ void operator () (const P &x)
+ {
+ std::cout << '\t' << x.first << ':' << x.second <<'\n';
+ }
+ };
+
+}
+
+void walk_data::operator () (const std::string &x)
+{
+ std::cout << "String:" << x <<'\n';
+}
+
+void walk_data::operator () (const tag &t)
+{
+ std::cout << "Tag:" << t.id << '\n';
+ std::cout << "Attributes\n";
+
+ std::for_each
+ (
+ t.attributes.begin(),
+ t.attributes.end(),
+ print_pair()
+ );
+ std::cout << "Children:\n";
+ std::for_each
+ (
+ t.children.begin(),
+ t.children.end(),
+ boost::apply_visitor(*this)
+ );
+ std::cout << "End of tag:" << t.id << '\n';
+}
diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.hpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.hpp
new file mode 100644
index 00000000..15f97593
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/tag.hpp
@@ -0,0 +1,33 @@
+// Copyright (c) 2005 Carl Barron. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef SIMPLE_XML_TAG_H
+#define SIMPLE_XML_TAG_H
+
+#include <boost/variant.hpp>
+#include <list>
+#include <map>
+#include <string>
+
+struct tag
+{
+ std::string id;
+ std::map<std::string,std::string> attributes;
+ typedef boost::variant<
+ std::string,
+ boost::recursive_wrapper<tag>
+ >
+ variant_type;
+ std::list<variant_type> children;
+};
+
+
+struct walk_data
+{
+ typedef void result_type;
+ void operator () (const std::string &x);
+ void operator () (const tag &t);
+};
+
+#endif
diff --git a/src/boost/libs/spirit/classic/example/intermediate/simple_xml/xml_g.hpp b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/xml_g.hpp
new file mode 100644
index 00000000..fb0a4c61
--- /dev/null
+++ b/src/boost/libs/spirit/classic/example/intermediate/simple_xml/xml_g.hpp
@@ -0,0 +1,186 @@
+// Copyright (c) 2005 Carl Barron. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef XML_G_H
+#define XML_G_H
+#define BOOST_SPIRIT_DEBUG
+#ifndef BOOST_SPIRIT_CLOSURE_LIMIT
+#define BOOST_SPIRIT_CLOSURE_LIMIT 10
+#endif
+
+#ifndef PHOENIX_LIMIT
+#define PHOENIX_LIMIT 10
+#endif
+
+#if BOOST_SPIRIT_CLOSURE_LIMIT < 6
+#undef BOOST_SPIRIT_CLOSURE_LIMIT
+#define BOOST_SPIRIT_CLOSURE_LIMIT 6
+#endif
+
+#if PHOENIX_LIMIT < BOOST_SPIRIT_CLOSURE_LIMIT
+#undef PHOENIX_LIMIT
+#define PHOENIX_LIMIT BOOST_SPIRIT_CLOSURE_LIMIT
+#endif
+
+#if 0
+#ifdef BOOST_SPIRIT_DEBUG_FLAGS
+#undef BOOST_SPIRIT_DEBUG_FLAGS
+#endif
+#define BOOST_SPIRIT_DEBUG_FLAGS (BOOST_SPIRIT_DEBUG_FLAGS_MAX - BOOST_SPIRIT_DEBUG_FLAGS_CLOSURES)
+#endif
+
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_attribute.hpp>
+#include <boost/spirit/include/phoenix1.hpp>
+#include "tag.hpp"
+#include "actions.hpp"
+#include <boost/variant.hpp>
+
+#include <string>
+#include <utility>
+
+namespace SP = BOOST_SPIRIT_CLASSIC_NS;
+using phoenix::arg1;
+using phoenix::arg2;
+using phoenix::construct_;
+using phoenix::var;
+
+struct str_cls:SP::closure<str_cls,std::string>
+{ member1 value;};
+
+struct attrib_cls:SP::closure
+<
+ attrib_cls,
+ std::pair<std::string,std::string>,
+ std::string,
+ std::string
+>
+{
+ member1 value;
+ member2 first;
+ member3 second;
+};
+
+struct tagged_cls:SP::closure
+<
+ tagged_cls,
+ tag,
+ std::string,
+ std::map<std::string,std::string>,
+ std::list<typename tag::variant_type>
+>
+{
+ member1 value;
+ member2 ID;
+ member3 attribs;
+ member4 children;
+};
+
+struct xml_g:SP::grammar<xml_g>
+{
+ std::list<tag> &tags;
+ xml_g(std::list<tag> &a):tags(a){}
+ template <class Scan>
+ struct definition
+ {
+ definition(const xml_g &s)
+ {
+ white = +SP::space_p
+ ;
+
+ tagged = (start_tag
+ >> *inner
+ >> end_tag
+ | simple_start_tag
+ )
+ [store_tag(tagged.value,tagged.ID,tagged.attribs,
+ tagged.children)]
+ ;
+
+ end_tag = SP::str_p("</")
+ >> SP::f_str_p(tagged.ID)
+ >> '>'
+ ;
+
+ inner = (tagged
+ | str) [push_child(tagged.children,arg1)]
+ ;
+
+ str = SP::lexeme_d[+(SP::anychar_p - '<')]
+ [str.value=construct_<std::string>(arg1,arg2)]
+ ;
+
+ top = +tagged
+ [push_back(var(s.tags),arg1)]
+ ;
+
+ starter = SP::ch_p('<')
+ >> SP::lexeme_d[+SP::alpha_p]
+ [tagged.ID = construct_<std::string>(arg1,arg2)]
+ >> *attrib
+ [store_in_map(tagged.attribs,arg1)]
+ >> !white
+ ;
+ start_tag = starter
+ >> '>'
+ ;
+
+ simple_start_tag = starter
+ >> "/>"
+ ;
+
+ attrib = white
+ >>SP::lexeme_d[+SP::alpha_p]
+ [attrib.first = construct_<std::string>(arg1,arg2)]
+ >> !white
+ >> '='
+ >> !white
+ >> '"'
+ >> SP::lexeme_d[+(SP::anychar_p - '"')]
+ [attrib.second = construct_<std::string>(arg1,arg2)]
+ >> SP::ch_p('"')
+ [attrib.value = construct_
+ <
+ std::pair
+ <
+ std::string,
+ std::string
+ >
+ >(attrib.first,attrib.second)]
+ ;
+ BOOST_SPIRIT_DEBUG_RULE(tagged);
+ BOOST_SPIRIT_DEBUG_RULE(end_tag);
+ BOOST_SPIRIT_DEBUG_RULE(inner);
+ BOOST_SPIRIT_DEBUG_RULE(str);
+ BOOST_SPIRIT_DEBUG_RULE(top);
+ BOOST_SPIRIT_DEBUG_RULE(start_tag);
+ BOOST_SPIRIT_DEBUG_RULE(attrib);
+ BOOST_SPIRIT_DEBUG_RULE(white);
+ BOOST_SPIRIT_DEBUG_RULE(starter);
+ BOOST_SPIRIT_DEBUG_RULE(simple_start_tag);
+ }
+
+ // actions
+ push_back_f push_back;
+ push_child_f push_child;
+ store_in_map_f store_in_map;
+ store_tag_f store_tag;
+ // rules
+ SP::rule<Scan,tagged_cls::context_t> tagged;
+ SP::rule<Scan> end_tag;
+ SP::rule<Scan> inner;
+ SP::rule<Scan,str_cls::context_t> str;
+ SP::rule<Scan> top;
+ SP::rule<Scan> starter;
+ SP::rule<Scan> simple_start_tag;
+ SP::rule<Scan> start_tag;
+ SP::rule<Scan> white;
+ SP::rule<Scan,attrib_cls::context_t> attrib;
+ SP::rule<Scan> const &start() const
+ { return top;}
+ };
+};
+
+#endif
+