summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/spirit/example/qi
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/spirit/example/qi')
-rw-r--r--src/boost/libs/spirit/example/qi/Jamfile48
-rw-r--r--src/boost/libs/spirit/example/qi/actions.cpp108
-rw-r--r--src/boost/libs/spirit/example/qi/adapt_template_struct.cpp92
-rw-r--r--src/boost/libs/spirit/example/qi/boost_array.cpp119
-rw-r--r--src/boost/libs/spirit/example/qi/calc_utree.cpp166
-rw-r--r--src/boost/libs/spirit/example/qi/calc_utree_ast.cpp164
-rw-r--r--src/boost/libs/spirit/example/qi/calc_utree_naive.cpp134
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/Jamfile132
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc1.cpp118
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp131
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc3.cpp124
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc4.cpp285
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc5.cpp339
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc6.cpp373
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp78
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp117
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp222
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp85
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp93
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp53
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp94
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp101
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp32
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp75
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.cpp66
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp52
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/annotation.hpp78
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/ast.hpp172
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp382
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.hpp92
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/error_handler.hpp93
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.hpp68
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression_def.hpp159
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/main.cpp97
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.hpp37
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement_def.hpp111
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp163
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.hpp77
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/annotation.hpp95
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/ast.hpp275
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.cpp628
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.hpp123
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/error_handler.hpp93
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.hpp75
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression_def.hpp131
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.hpp32
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function_def.hpp71
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/main.cpp121
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/skipper.hpp40
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.hpp38
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement_def.hpp128
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.cpp159
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.hpp82
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/annotation.hpp95
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ast.hpp209
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.cpp622
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.hpp123
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/config.hpp51
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer.hpp483
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer_generate.cpp43
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_switch_lexer.hpp873
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/error_handler.hpp105
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.hpp58
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression_def.hpp94
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.hpp36
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function_def.hpp64
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ids.hpp154
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.cpp17
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.hpp128
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer_def.hpp74
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/main.cpp131
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.hpp42
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement_def.hpp123
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.cpp160
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.hpp82
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp141
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp240
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp1141
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp311
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp51
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp483
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp43
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp873
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp99
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp59
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp104
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp36
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp64
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp160
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp17
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp144
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp100
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp156
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp42
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp126
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp43
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp121
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/error.cnj16
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/factorial.cnj15
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/operators.cnj137
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/pow2.cnj19
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/precedence.cnj8
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/annotation.hpp95
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/ast.hpp225
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.cpp538
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.hpp118
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/error_handler.hpp93
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.hpp79
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression_def.hpp181
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.hpp32
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function_def.hpp71
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/main.cpp121
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/skipper.hpp40
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.hpp38
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement_def.hpp124
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.cpp159
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.hpp82
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/1.mini19
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/2.mini15
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/3.mini17
-rw-r--r--src/boost/libs/spirit/example/qi/complex_number.cpp101
-rw-r--r--src/boost/libs/spirit/example/qi/custom_string.cpp113
-rw-r--r--src/boost/libs/spirit/example/qi/display_attribute_type.cpp22
-rw-r--r--src/boost/libs/spirit/example/qi/display_attribute_type.hpp59
-rw-r--r--src/boost/libs/spirit/example/qi/employee.cpp151
-rw-r--r--src/boost/libs/spirit/example/qi/expect.cpp112
-rw-r--r--src/boost/libs/spirit/example/qi/german_floating_point.cpp48
-rw-r--r--src/boost/libs/spirit/example/qi/iter_pos.hpp83
-rw-r--r--src/boost/libs/spirit/example/qi/iter_pos_parser.cpp51
-rw-r--r--src/boost/libs/spirit/example/qi/key_value_sequence.cpp78
-rw-r--r--src/boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp83
-rw-r--r--src/boost/libs/spirit/example/qi/key_value_sequence_ordered.cpp78
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml1.cpp242
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml2.cpp237
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml3.cpp258
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml_samples/1.toyxml1
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml_samples/2.toyxml1
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml_samples/3.toyxml5
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml_samples/4.toyxml1
-rw-r--r--src/boost/libs/spirit/example/qi/nabialek.cpp98
-rw-r--r--src/boost/libs/spirit/example/qi/num_list1.cpp90
-rw-r--r--src/boost/libs/spirit/example/qi/num_list2.cpp109
-rw-r--r--src/boost/libs/spirit/example/qi/num_list3.cpp108
-rw-r--r--src/boost/libs/spirit/example/qi/num_list4.cpp106
-rw-r--r--src/boost/libs/spirit/example/qi/parse_date.cpp125
-rw-r--r--src/boost/libs/spirit/example/qi/porting_guide_classic.cpp108
-rw-r--r--src/boost/libs/spirit/example/qi/porting_guide_qi.cpp106
-rw-r--r--src/boost/libs/spirit/example/qi/reference.cpp1481
-rw-r--r--src/boost/libs/spirit/example/qi/reorder_struct.cpp130
-rw-r--r--src/boost/libs/spirit/example/qi/roman.cpp188
-rw-r--r--src/boost/libs/spirit/example/qi/sum.cpp106
-rw-r--r--src/boost/libs/spirit/example/qi/typeof.cpp65
-rw-r--r--src/boost/libs/spirit/example/qi/unescaped_string.cpp72
169 files changed, 22460 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/example/qi/Jamfile b/src/boost/libs/spirit/example/qi/Jamfile
new file mode 100644
index 00000000..a071c0d2
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/Jamfile
@@ -0,0 +1,48 @@
+#==============================================================================
+# Copyright (c) 2001-2007 Joel de Guzman
+#
+# 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)
+#==============================================================================
+project spirit-qi-example
+ : requirements
+ <c++-template-depth>300
+ :
+ :
+ ;
+
+exe actions_ : actions.cpp ;
+exe sum : sum.cpp ;
+exe complex_number : complex_number.cpp ;
+exe employee : employee.cpp ;
+exe roman : roman.cpp ;
+exe reference : reference.cpp ;
+exe mini_xml1 : mini_xml1.cpp ;
+exe mini_xml2 : mini_xml2.cpp ;
+exe mini_xml3 : mini_xml3.cpp ;
+exe num_list1 : num_list1.cpp ;
+exe num_list2 : num_list2.cpp ;
+exe num_list3 : num_list3.cpp ;
+exe num_list4 : num_list4.cpp ;
+exe reorder_struct : reorder_struct.cpp ;
+exe parse_date : parse_date.cpp ;
+exe expect : expect.cpp ;
+
+exe key_value_sequence : key_value_sequence.cpp ;
+exe key_value_sequence_ordered : key_value_sequence_ordered.cpp ;
+exe key_value_sequence_empty_value : key_value_sequence_empty_value.cpp ;
+
+exe iter_pos_parser : iter_pos_parser.cpp ;
+exe boost_array : boost_array.cpp ;
+exe display_attribute_type : display_attribute_type.cpp ;
+exe adapt_template_struct : adapt_template_struct.cpp ;
+
+exe unescaped_string : unescaped_string.cpp ;
+
+exe calc_utree_naive : calc_utree_naive.cpp ;
+exe calc_utree_ast : calc_utree_ast.cpp ;
+exe calc_utree : calc_utree.cpp ;
+
+exe nabialek : nabialek.cpp ;
+exe typeof : typeof.cpp ;
+
diff --git a/src/boost/libs/spirit/example/qi/actions.cpp b/src/boost/libs/spirit/example/qi/actions.cpp
new file mode 100644
index 00000000..c5379703
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/actions.cpp
@@ -0,0 +1,108 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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 <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/bind.hpp>
+
+#include <iostream>
+
+// Presented are various ways to attach semantic actions
+// * Using plain function pointer
+// * Using simple function object
+// * Using boost.bind with a plain function
+// * Using boost.bind with a member function
+// * Using boost.lambda
+
+//[tutorial_semantic_action_functions
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ // A plain function
+ void print(int const& i)
+ {
+ std::cout << i << std::endl;
+ }
+
+ // A member function
+ struct writer
+ {
+ void print(int const& i) const
+ {
+ std::cout << i << std::endl;
+ }
+ };
+
+ // A function object
+ struct print_action
+ {
+ void operator()(int const& i, qi::unused_type, qi::unused_type) const
+ {
+ std::cout << i << std::endl;
+ }
+ };
+}
+//]
+
+int main()
+{
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::parse;
+ using client::print;
+ using client::writer;
+ using client::print_action;
+
+ { // example using plain function
+
+ char const *first = "{42}", *last = first + std::strlen(first);
+ //[tutorial_attach_actions1
+ parse(first, last, '{' >> int_[&print] >> '}');
+ //]
+ }
+
+ { // example using simple function object
+
+ char const *first = "{43}", *last = first + std::strlen(first);
+ //[tutorial_attach_actions2
+ parse(first, last, '{' >> int_[print_action()] >> '}');
+ //]
+ }
+
+ { // example using boost.bind with a plain function
+
+ char const *first = "{44}", *last = first + std::strlen(first);
+ //[tutorial_attach_actions3
+ parse(first, last, '{' >> int_[boost::bind(&print, _1)] >> '}');
+ //]
+ }
+
+ { // example using boost.bind with a member function
+
+ char const *first = "{44}", *last = first + std::strlen(first);
+ //[tutorial_attach_actions4
+ writer w;
+ parse(first, last, '{' >> int_[boost::bind(&writer::print, &w, _1)] >> '}');
+ //]
+ }
+
+ { // example using boost.lambda
+
+ namespace lambda = boost::lambda;
+ char const *first = "{45}", *last = first + std::strlen(first);
+ using lambda::_1;
+ //[tutorial_attach_actions5
+ parse(first, last, '{' >> int_[std::cout << _1 << '\n'] >> '}');
+ //]
+ }
+
+ return 0;
+}
+
+
+
+
diff --git a/src/boost/libs/spirit/example/qi/adapt_template_struct.cpp b/src/boost/libs/spirit/example/qi/adapt_template_struct.cpp
new file mode 100644
index 00000000..360707d1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/adapt_template_struct.cpp
@@ -0,0 +1,92 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example demonstrates a trick allowing to adapt a template data
+// structure as a Fusion sequence in order to use is for direct attribute
+// propagation. For more information see
+// http://boost-spirit.com/home/2010/02/08/how-to-adapt-templates-as-a-fusion-sequence
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace qi = boost::spirit::qi;
+namespace fusion = boost::fusion;
+
+namespace client
+{
+ template <typename A, typename B>
+ struct data
+ {
+ A a;
+ B b;
+ };
+
+ template <typename Iterator, typename A, typename B>
+ struct data_grammar : qi::grammar<Iterator, data<A, B>()>
+ {
+ data_grammar() : data_grammar::base_type(start)
+ {
+ start = real_start;
+ real_start = qi::auto_ >> ',' >> qi::auto_;
+ }
+
+ qi::rule<Iterator, data<A, B>()> start;
+ qi::rule<Iterator, fusion::vector<A&, B&>()> real_start;
+ };
+}
+
+namespace boost { namespace spirit { namespace traits
+{
+ template <typename A, typename B>
+ struct transform_attribute<client::data<A, B>, fusion::vector<A&, B&>, qi::domain>
+ {
+ typedef fusion::vector<A&, B&> type;
+
+ static type pre(client::data<A, B>& val) { return type(val.a, val.b); }
+ static void post(client::data<A, B>&, fusion::vector<A&, B&> const&) {}
+ static void fail(client::data<A, B>&) {}
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA parser for Spirit utilizing an adapted template ...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me two comma separated integers:\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ client::data_grammar<std::string::const_iterator, long, int> g; // Our grammar
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::data<long, int> d;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, g, qi::space, d);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << d.a << "," << d.b << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/boost_array.cpp b/src/boost/libs/spirit/example/qi/boost_array.cpp
new file mode 100644
index 00000000..66485b97
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/boost_array.cpp
@@ -0,0 +1,119 @@
+// Copyright (c) 2009 Erik Bryan
+// Copyright (c) 2007-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <string>
+#include <vector>
+
+#include <boost/array.hpp>
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace qi = boost::spirit::qi;
+namespace ascii = boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// create a wrapper holding the boost::array and a current insertion point
+namespace client
+{
+ namespace detail
+ {
+ template <typename T>
+ struct adapt_array;
+
+ template <typename T, std::size_t N>
+ struct adapt_array<boost::array<T, N> >
+ {
+ typedef boost::array<T, N> array_type;
+
+ adapt_array(array_type& arr)
+ : arr_(arr), current_(0) {}
+
+ // expose a push_back function compatible with std containers
+ bool push_back(typename array_type::value_type const& val)
+ {
+ // if the array is full, we need to bail out
+ // returning false will fail the parse
+ if (current_ >= N)
+ return false;
+
+ arr_[current_++] = val;
+ return true;
+ }
+
+ array_type& arr_;
+ std::size_t current_;
+ };
+ }
+
+ namespace result_of
+ {
+ template <typename T>
+ struct adapt_array;
+
+ template <typename T, std::size_t N>
+ struct adapt_array<boost::array<T, N> >
+ {
+ typedef detail::adapt_array<boost::array<T, N> > type;
+ };
+ }
+
+ template <typename T, std::size_t N>
+ inline detail::adapt_array<boost::array<T, N> >
+ adapt_array(boost::array<T, N>& arr)
+ {
+ return detail::adapt_array<boost::array<T, N> >(arr);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// specialize Spirit's container specific customization points for our adaptor
+namespace boost { namespace spirit { namespace traits
+{
+ template <typename T, std::size_t N>
+ struct is_container<client::detail::adapt_array<boost::array<T, N> > >
+ : boost::mpl::true_
+ {};
+
+ template <typename T, std::size_t N>
+ struct container_value<client::detail::adapt_array<boost::array<T, N> > >
+ {
+ typedef T type; // value type of container
+ };
+
+ template <typename T, std::size_t N>
+ struct push_back_container<
+ client::detail::adapt_array<boost::array<T, N> >, T>
+ {
+ static bool call(client::detail::adapt_array<boost::array<T, N> >& c
+ , T const& val)
+ {
+ return c.push_back(val);
+ }
+ };
+}}}
+
+int main()
+{
+ typedef std::string::const_iterator iterator_type;
+ typedef boost::array<int, 2> array_type;
+ typedef client::result_of::adapt_array<array_type>::type adapted_type;
+
+ array_type arr;
+
+ std::string str = "1 2";
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+
+ qi::rule<iterator_type, adapted_type(), ascii::space_type> r = *qi::int_;
+
+ adapted_type attr = client::adapt_array(arr);
+ bool result = qi::phrase_parse(iter, end, r, ascii::space, attr);
+
+ if (result)
+ std::cout << "Parsed: " << arr[0] << ", " << arr[1] << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/calc_utree.cpp b/src/boost/libs/spirit/example/qi/calc_utree.cpp
new file mode 100644
index 00000000..00293df3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/calc_utree.cpp
@@ -0,0 +1,166 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Plain calculator example demonstrating the grammar. The parser is a
+// syntax checker only and does not do any semantic evaluation.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ HK November 30, 2010 ] spirit2/utree
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// #define BOOST_SPIRIT_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+#include <iostream>
+#include <string>
+
+#if BOOST_PHOENIX_VERSION == 0x2000
+namespace boost { namespace phoenix
+{
+ // There's a bug in the Phoenix V2 type deduction mechanism that prevents
+ // correct return type deduction for the math operations below. Newer
+ // versions of Phoenix will be switching to BOOST_TYPEOF. In the meantime,
+ // we will use the specializations helping with return type deduction
+ // below:
+ template <>
+ struct result_of_plus<spirit::utree&, spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+
+ template <>
+ struct result_of_minus<spirit::utree&, spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+
+ template <>
+ struct result_of_multiplies<spirit::utree&, spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+
+ template <>
+ struct result_of_divides<spirit::utree&, spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+
+ template <>
+ struct result_of_negate<spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+}}
+#endif
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace spirit = boost::spirit;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ using qi::uint_;
+ using qi::_val;
+ using qi::_1;
+
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [_val = _val + _1])
+ | ('-' >> term [_val = _val - _1])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [_val = _val * _1])
+ | ('/' >> factor [_val = _val / _1])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [_val = -_1])
+ | ('+' >> factor [_val = _1])
+ ;
+
+ BOOST_SPIRIT_DEBUG_NODE(expression);
+ BOOST_SPIRIT_DEBUG_NODE(term);
+ BOOST_SPIRIT_DEBUG_NODE(factor);
+ }
+
+ qi::rule<Iterator, ascii::space_type, spirit::utree()> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ using boost::spirit::ascii::space;
+ using boost::spirit::utree;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ utree ut;
+ bool r = phrase_parse(iter, end, calc, space, ut);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded: " << ut << "\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/calc_utree_ast.cpp b/src/boost/libs/spirit/example/qi/calc_utree_ast.cpp
new file mode 100644
index 00000000..3465ba08
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/calc_utree_ast.cpp
@@ -0,0 +1,164 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Plain calculator example demonstrating the grammar. The parser is a
+// syntax checker only and does not do any semantic evaluation.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ HK November 30, 2010 ] spirit2/utree
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// #define BOOST_SPIRIT_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace spirit = boost::spirit;
+
+ struct expr
+ {
+ template <typename T1, typename T2 = void>
+ struct result { typedef void type; };
+
+ expr(char op) : op(op) {}
+
+ void operator()(spirit::utree& expr, spirit::utree const& rhs) const
+ {
+ spirit::utree lhs;
+ lhs.swap(expr);
+ expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
+ expr.push_back(lhs);
+ expr.push_back(rhs);
+ }
+
+ char const op;
+ };
+ boost::phoenix::function<expr> const plus = expr('+');
+ boost::phoenix::function<expr> const minus = expr('-');
+ boost::phoenix::function<expr> const times = expr('*');
+ boost::phoenix::function<expr> const divide = expr('/');
+
+ struct negate_expr
+ {
+ template <typename T1, typename T2 = void>
+ struct result { typedef void type; };
+
+ void operator()(spirit::utree& expr, spirit::utree const& rhs) const
+ {
+ char const op = '-';
+ expr.clear();
+ expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
+ expr.push_back(rhs);
+ }
+ };
+ boost::phoenix::function<negate_expr> neg;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ using qi::uint_;
+ using qi::_val;
+ using qi::_1;
+
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [plus(_val, _1)])
+ | ('-' >> term [minus(_val, _1)])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [times(_val, _1)])
+ | ('/' >> factor [divide(_val, _1)])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [neg(_val, _1)])
+ | ('+' >> factor [_val = _1])
+ ;
+
+ BOOST_SPIRIT_DEBUG_NODE(expression);
+ BOOST_SPIRIT_DEBUG_NODE(term);
+ BOOST_SPIRIT_DEBUG_NODE(factor);
+ }
+
+ qi::rule<Iterator, ascii::space_type, spirit::utree()> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ using boost::spirit::ascii::space;
+ using boost::spirit::utree;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ utree ut;
+ bool r = phrase_parse(iter, end, calc, space, ut);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded: " << ut << "\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/calc_utree_naive.cpp b/src/boost/libs/spirit/example/qi/calc_utree_naive.cpp
new file mode 100644
index 00000000..c6ac3ddb
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/calc_utree_naive.cpp
@@ -0,0 +1,134 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Plain calculator example demonstrating the grammar. The parser is a
+// syntax checker only and does not do any semantic evaluation.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ HK November 30, 2010 ] spirit2/utree
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// This rather naive example demonstrates that you can pass an instance of a
+// utree as the attribute for almost any grammar. As the result the utree will
+// be filled with the parse tree as generated during the parsing. This is most
+// of the time not what's desired, but is usually a good first step in order to
+// prepare your grammar to generate a customized AST. See the calc_utree_ast
+// example for a modified version of this grammar filling the attribute with a
+// AST (abstract syntax tree) representing the math expression as matched from
+// the input.
+
+// #define BOOST_SPIRIT_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/support_utree.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace spirit = boost::spirit;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ using qi::uint_;
+ using qi::char_;
+
+ expression =
+ term
+ >> *( (char_('+') >> term)
+ | (char_('-') >> term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( (char_('*') >> factor)
+ | (char_('/') >> factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' >> expression >> ')'
+ | (char_('-') >> factor)
+ | (char_('+') >> factor)
+ ;
+
+ BOOST_SPIRIT_DEBUG_NODE(expression);
+ BOOST_SPIRIT_DEBUG_NODE(term);
+ BOOST_SPIRIT_DEBUG_NODE(factor);
+ }
+
+ qi::rule<Iterator, ascii::space_type, spirit::utree()> expression;
+ qi::rule<Iterator, ascii::space_type, spirit::utree::list_type()> term;
+ qi::rule<Iterator, ascii::space_type, spirit::utree::list_type()> factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ using boost::spirit::ascii::space;
+ using boost::spirit::utree;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ utree ut;
+ bool r = phrase_parse(iter, end, calc, space, ut);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded: " << ut << "\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/Jamfile b/src/boost/libs/spirit/example/qi/compiler_tutorial/Jamfile
new file mode 100644
index 00000000..bda2fad4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/Jamfile
@@ -0,0 +1,132 @@
+#==============================================================================
+# Copyright (c) 2001-2011 Joel de Guzman
+#
+# 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)
+#==============================================================================
+project spirit-qi-compiler_tutorial
+ : requirements
+ <c++-template-depth>300
+ :
+ ;
+
+import modules ;
+
+exe calc1 : calc1.cpp ;
+exe calc2 : calc2.cpp ;
+exe calc3 : calc3.cpp ;
+exe calc4 : calc4.cpp ;
+exe calc5 : calc5.cpp ;
+exe calc6 : calc6.cpp ;
+
+exe calc7 :
+ calc7/vm.cpp
+ calc7/compiler.cpp
+ calc7/expression.cpp
+ calc7/statement.cpp
+ calc7/main.cpp
+;
+
+exe calc8 :
+ calc8/vm.cpp
+ calc8/compiler.cpp
+ calc8/expression.cpp
+ calc8/statement.cpp
+ calc8/main.cpp
+;
+
+exe mini_c :
+ mini_c/vm.cpp
+ mini_c/compiler.cpp
+ mini_c/expression.cpp
+ mini_c/statement.cpp
+ mini_c/function.cpp
+ mini_c/main.cpp
+;
+
+exe conjure1 :
+ conjure1/vm.cpp
+ conjure1/compiler.cpp
+ conjure1/expression.cpp
+ conjure1/statement.cpp
+ conjure1/function.cpp
+ conjure1/main.cpp
+;
+
+exe conjure2 :
+ conjure2/compiler.cpp
+ conjure2/expression.cpp
+ conjure2/function.cpp
+ conjure2/lexer.cpp
+ conjure2/main.cpp
+ conjure2/statement.cpp
+ conjure2/vm.cpp
+;
+
+#==============================================================================
+# conjure3 and above require LLVM. Make sure you provide the
+# LLVM_PATH in your bjam invocation. E.g.:
+#
+# bjam -sLLVM_PATH=C:/dev/llvm conjure3
+#
+#==============================================================================
+
+if [ modules.peek : LLVM_PATH ]
+{
+ LLVM_PATH = [ modules.peek : LLVM_PATH ] ;
+}
+
+if $(LLVM_PATH)
+{
+ path-constant LLVM_LIB_DEBUG_PATH : $(LLVM_PATH)/lib/Debug ;
+ path-constant LLVM_LIB_RELEASE_PATH : $(LLVM_PATH)/lib/Release ;
+
+ llvm_linker_flags =
+ "advapi32.lib"
+ "shell32.lib"
+ ;
+
+ llvm_debug_libs = [ glob $(LLVM_LIB_DEBUG_PATH)/LLVM*.lib ] ;
+ llvm_release_libs = [ glob $(LLVM_LIB_RELEASE_PATH)/LLVM*.lib ] ;
+
+ rule build_exe_1 ( target-name : sources + : requirements * )
+ {
+ local llvm_lib ;
+ if <variant>debug in $(requirements)
+ {
+ llvm_lib = $(llvm_debug_libs) ;
+ }
+ else
+ {
+ llvm_lib = $(llvm_release_libs) ;
+ }
+
+ exe $(target-name)
+ : $(sources)
+ $(llvm_lib)
+ : $(requirements)
+ <toolset>msvc
+ <include>$(LLVM_PATH)/include
+ <linkflags>$(llvm_linker_flags)
+ ;
+ }
+
+ rule build_exe ( target-name : sources + )
+ {
+ build_exe_1 $(target-name) : $(sources) : <variant>debug ;
+ build_exe_1 $(target-name) : $(sources) : <variant>release ;
+ }
+
+ build_exe conjure3 :
+ conjure3/compiler.cpp
+ conjure3/expression.cpp
+ conjure3/function.cpp
+ conjure3/lexer.cpp
+ conjure3/main.cpp
+ conjure3/statement.cpp
+ conjure3/vm.cpp
+ ;
+}
+
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc1.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc1.cpp
new file mode 100644
index 00000000..d070172f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc1.cpp
@@ -0,0 +1,118 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Plain calculator example demonstrating the grammar. The parser is a
+// syntax checker only and does not do any semantic evaluation.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ JDG February 21, 2011 ] spirit2.5
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::uint_type uint_;
+
+ expression =
+ term
+ >> *( ('+' >> term)
+ | ('-' >> term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( ('*' >> factor)
+ | ('/' >> factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' >> expression >> ')'
+ | ('-' >> factor)
+ | ('+' >> factor)
+ ;
+ }
+
+ qi::rule<Iterator, ascii::space_type> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ boost::spirit::ascii::space_type space; // Our skipper
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, calc, space);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \" " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp
new file mode 100644
index 00000000..92e03f49
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp
@@ -0,0 +1,131 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating the grammar and semantic actions
+// using plain functions. The parser prints code suitable for a stack
+// based virtual machine.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ JDG February 21, 2011 ] spirit2.5
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Semantic actions
+ ////////////////////////////////////////////////////////1///////////////////////
+ namespace
+ {
+ void do_int(int n) { std::cout << "push " << n << std::endl; }
+ void do_add() { std::cout << "add\n"; }
+ void do_subt() { std::cout << "subtract\n"; }
+ void do_mult() { std::cout << "mult\n"; }
+ void do_div() { std::cout << "divide\n"; }
+ void do_neg() { std::cout << "negate\n"; }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::uint_type uint_;
+
+ expression =
+ term
+ >> *( ('+' >> term [&do_add])
+ | ('-' >> term [&do_subt])
+ )
+ ;
+
+ term =
+ factor
+ >> *( ('*' >> factor [&do_mult])
+ | ('/' >> factor [&do_div])
+ )
+ ;
+
+ factor =
+ uint_ [&do_int]
+ | '(' >> expression >> ')'
+ | ('-' >> factor [&do_neg])
+ | ('+' >> factor)
+ ;
+ }
+
+ qi::rule<Iterator, ascii::space_type> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ boost::spirit::ascii::space_type space; // Our skipper
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, calc, space);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \" " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc3.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc3.cpp
new file mode 100644
index 00000000..4f214e30
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc3.cpp
@@ -0,0 +1,124 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A calculator example demonstrating the grammar and semantic actions
+// using phoenix to do the actual expression evaluation. The parser is
+// essentially an "interpreter" that evaluates expressions on the fly.
+//
+// [ JDG June 29, 2002 ] spirit1
+// [ JDG March 5, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, int(), ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::_val_type _val;
+ qi::_1_type _1;
+ qi::uint_type uint_;
+
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [_val += _1])
+ | ('-' >> term [_val -= _1])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [_val *= _1])
+ | ('/' >> factor [_val /= _1])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [_val = -_1])
+ | ('+' >> factor [_val = _1])
+ ;
+ }
+
+ qi::rule<Iterator, int(), ascii::space_type> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ boost::spirit::ascii::space_type space; // Our skipper
+ calculator calc; // Our grammar
+
+ std::string str;
+ int result;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, calc, space, result);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "result = " << result << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \" " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc4.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc4.cpp
new file mode 100644
index 00000000..645926f7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc4.cpp
@@ -0,0 +1,285 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST. The AST,
+// once created, is traversed, 1) To print its contents and
+// 2) To evaluate the result.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct program;
+
+ typedef boost::variant<
+ nil
+ , unsigned int
+ , boost::recursive_wrapper<signed_>
+ , boost::recursive_wrapper<program>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct program
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::signed_,
+ (char, sign)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (char, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::program,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST Printer
+ ///////////////////////////////////////////////////////////////////////////
+ struct printer
+ {
+ typedef void result_type;
+
+ void operator()(nil) const {}
+ void operator()(unsigned int n) const { std::cout << n; }
+
+ void operator()(operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': std::cout << " add"; break;
+ case '-': std::cout << " subt"; break;
+ case '*': std::cout << " mult"; break;
+ case '/': std::cout << " div"; break;
+ }
+ }
+
+ void operator()(signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': std::cout << " neg"; break;
+ case '+': std::cout << " pos"; break;
+ }
+ }
+
+ void operator()(program const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(operation const& oper, x.rest)
+ {
+ std::cout << ' ';
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST evaluator
+ ///////////////////////////////////////////////////////////////////////////
+ struct eval
+ {
+ typedef int result_type;
+
+ int operator()(nil) const { BOOST_ASSERT(0); return 0; }
+ int operator()(unsigned int n) const { return n; }
+
+ int operator()(operation const& x, int lhs) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': return lhs + rhs;
+ case '-': return lhs - rhs;
+ case '*': return lhs * rhs;
+ case '/': return lhs / rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(signed_ const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': return -rhs;
+ case '+': return +rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(program const& x) const
+ {
+ int state = boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(operation const& oper, x.rest)
+ {
+ state = (*this)(oper, state);
+ }
+ return state;
+ }
+ };
+}}
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ast::program(), ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::uint_type uint_;
+ qi::char_type char_;
+
+ expression =
+ term
+ >> *( (char_('+') >> term)
+ | (char_('-') >> term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( (char_('*') >> factor)
+ | (char_('/') >> factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' >> expression >> ')'
+ | (char_('-') >> factor)
+ | (char_('+') >> factor)
+ ;
+ }
+
+ qi::rule<Iterator, ast::program(), ascii::space_type> expression;
+ qi::rule<Iterator, ast::program(), ascii::space_type> term;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+ typedef client::ast::program ast_program;
+ typedef client::ast::printer ast_print;
+ typedef client::ast::eval ast_eval;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ calculator calc; // Our grammar
+ ast_program program; // Our program (AST)
+ ast_print print; // Prints the program
+ ast_eval eval; // Evaluates the program
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ boost::spirit::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, program);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ print(program);
+ std::cout << "\nResult: " << eval(program) << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \" " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc5.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc5.cpp
new file mode 100644
index 00000000..8aa71342
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc5.cpp
@@ -0,0 +1,339 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Same as Calc4, this time, we'll incorporate debugging support,
+// plus error handling and reporting.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Define this to enable debugging
+#define BOOST_SPIRIT_QI_DEBUG
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+//#define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct program;
+
+ typedef boost::variant<
+ nil
+ , unsigned int
+ , boost::recursive_wrapper<signed_>
+ , boost::recursive_wrapper<program>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct program
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ // print function for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::signed_,
+ (char, sign)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (char, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::program,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST Printer
+ ///////////////////////////////////////////////////////////////////////////
+ struct printer
+ {
+ typedef void result_type;
+
+ void operator()(nil) const {}
+ void operator()(unsigned int n) const { std::cout << n; }
+
+ void operator()(operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': std::cout << " add"; break;
+ case '-': std::cout << " subt"; break;
+ case '*': std::cout << " mult"; break;
+ case '/': std::cout << " div"; break;
+ }
+ }
+
+ void operator()(signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': std::cout << " neg"; break;
+ case '+': std::cout << " pos"; break;
+ }
+ }
+
+ void operator()(program const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(operation const& oper, x.rest)
+ {
+ std::cout << ' ';
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST evaluator
+ ///////////////////////////////////////////////////////////////////////////
+ struct eval
+ {
+ typedef int result_type;
+
+ int operator()(nil) const { BOOST_ASSERT(0); return 0; }
+ int operator()(unsigned int n) const { return n; }
+
+ int operator()(operation const& x, int lhs) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': return lhs + rhs;
+ case '-': return lhs - rhs;
+ case '*': return lhs * rhs;
+ case '/': return lhs / rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(signed_ const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': return -rhs;
+ case '+': return +rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(program const& x) const
+ {
+ int state = boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(operation const& oper, x.rest)
+ {
+ state = (*this)(oper, state);
+ }
+ return state;
+ }
+ };
+}}
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ using boost::phoenix::function;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ struct error_handler_
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ template <typename Iterator>
+ void operator()(
+ qi::info const& what
+ , Iterator err_pos, Iterator last) const
+ {
+ std::cout
+ << "Error! Expecting "
+ << what // what failed?
+ << " here: \""
+ << std::string(err_pos, last) // iterators to error-pos, end
+ << "\""
+ << std::endl
+ ;
+ }
+ };
+
+ function<error_handler_> const error_handler = error_handler_();
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ast::program(), ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ using qi::on_error;
+ using qi::fail;
+
+ expression =
+ term
+ >> *( (char_('+') > term)
+ | (char_('-') > term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( (char_('*') > factor)
+ | (char_('/') > factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' > expression > ')'
+ | (char_('-') > factor)
+ | (char_('+') > factor)
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODE(expression);
+ BOOST_SPIRIT_DEBUG_NODE(term);
+ BOOST_SPIRIT_DEBUG_NODE(factor);
+
+ // Error handling
+ on_error<fail>(expression, error_handler(_4, _3, _2));
+ }
+
+ qi::rule<Iterator, ast::program(), ascii::space_type> expression;
+ qi::rule<Iterator, ast::program(), ascii::space_type> term;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+ typedef client::ast::program ast_program;
+ typedef client::ast::printer ast_print;
+ typedef client::ast::eval ast_eval;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ calculator calc; // Our grammar
+ ast_program program; // Our program (AST)
+ ast_print print; // Prints the program
+ ast_eval eval; // Evaluates the program
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ boost::spirit::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, program);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ print(program);
+ std::cout << "\nResult: " << eval(program) << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc6.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc6.cpp
new file mode 100644
index 00000000..af362f3d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc6.cpp
@@ -0,0 +1,373 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Yet another calculator example! This time, we will compile to a simple
+// virtual machine. This is actually one of the very first Spirit example
+// circa 2000. Now, it's ported to Spirit2.
+//
+// [ JDG Sometime 2000 ] pre-boost
+// [ JDG September 18, 2002 ] spirit1
+// [ JDG April 8, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Define this to enable debugging
+//#define BOOST_SPIRIT_QI_DEBUG
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+//#define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct expression;
+
+ typedef boost::variant<
+ nil
+ , unsigned int
+ , boost::recursive_wrapper<signed_>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ // print function for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::signed_,
+ (char, sign)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (char, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+ op_int, // push constant integer into the stack
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ int top() const { return stack_ptr[-1]; };
+ void execute(std::vector<int> const& code);
+
+ private:
+
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+ };
+
+ void vmachine::execute(std::vector<int> const& code)
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+ stack_ptr = stack.begin();
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef void result_type;
+
+ std::vector<int>& code;
+ compiler(std::vector<int>& code)
+ : code(code) {}
+
+ void operator()(ast::nil) const { BOOST_ASSERT(0); }
+ void operator()(unsigned int n) const
+ {
+ code.push_back(op_int);
+ code.push_back(n);
+ }
+
+ void operator()(ast::operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': code.push_back(op_add); break;
+ case '-': code.push_back(op_sub); break;
+ case '*': code.push_back(op_mul); break;
+ case '/': code.push_back(op_div); break;
+ default: BOOST_ASSERT(0); break;
+ }
+ }
+
+ void operator()(ast::signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': code.push_back(op_neg); break;
+ case '+': break;
+ default: BOOST_ASSERT(0); break;
+ }
+ }
+
+ void operator()(ast::expression const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(ast::operation const& oper, x.rest)
+ {
+ (*this)(oper);
+ }
+ }
+ };
+
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ using boost::phoenix::function;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ struct error_handler_
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ template <typename Iterator>
+ void operator()(
+ qi::info const& what
+ , Iterator err_pos, Iterator last) const
+ {
+ std::cout
+ << "Error! Expecting "
+ << what // what failed?
+ << " here: \""
+ << std::string(err_pos, last) // iterators to error-pos, end
+ << "\""
+ << std::endl
+ ;
+ }
+ };
+
+ function<error_handler_> const error_handler = error_handler_();
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ast::expression(), ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ using qi::on_error;
+ using qi::fail;
+
+ expression =
+ term
+ >> *( (char_('+') > term)
+ | (char_('-') > term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( (char_('*') > factor)
+ | (char_('/') > factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' > expression > ')'
+ | (char_('-') > factor)
+ | (char_('+') > factor)
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expression)(term)(factor));
+
+ // Error handling
+ on_error<fail>(expression, error_handler(_4, _3, _2));
+ }
+
+ qi::rule<Iterator, ast::expression(), ascii::space_type> expression;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> term;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+ typedef client::ast::expression ast_expression;
+ typedef client::compiler compiler;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::vmachine mach; // Our virtual machine
+ std::vector<int> code; // Our VM code
+ calculator calc; // Our grammar
+ ast_expression expression; // Our program (AST)
+ compiler compile(code); // Compiles the program
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ boost::spirit::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, expression);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ compile(expression);
+ mach.execute(code);
+ std::cout << "\nResult: " << mach.top() << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp
new file mode 100644
index 00000000..37365283
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp
@@ -0,0 +1,78 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CALC7_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ this->dispatch(x, boost::is_base_of<ast::tagged, T>());
+ }
+
+ // This will catch all nodes except those inheriting from ast::tagged
+ template <typename T>
+ void dispatch(T& x, boost::mpl::false_) const
+ {
+ // (no-op) no need for tags
+ }
+
+ // This will catch all nodes inheriting from ast::tagged
+ template <typename T>
+ void dispatch(T& x, boost::mpl::true_) const
+ {
+ x.id = id;
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp
new file mode 100644
index 00000000..82fba496
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp
@@ -0,0 +1,117 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_AST_HPP)
+#define BOOST_SPIRIT_CALC7_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct signed_;
+ struct expression;
+
+ struct variable : tagged
+ {
+ variable(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , unsigned int
+ , variable
+ , boost::recursive_wrapper<signed_>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ variable lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ assignment assign;
+ };
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment>
+ statement;
+
+ typedef std::list<statement> statement_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+ inline std::ostream& operator<<(std::ostream& out, variable const& var) { out << var.name; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::signed_,
+ (char, sign)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (char, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::assignment, assign)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::variable, lhs)
+ (client::ast::expression, rhs)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp
new file mode 100644
index 00000000..8aa23017
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp
@@ -0,0 +1,222 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+
+namespace client { namespace code_gen
+{
+ void program::op(int a)
+ {
+ code.push_back(a);
+ }
+
+ void program::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ }
+
+ void program::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ }
+
+ int const* program::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void program::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void program::print_variables(std::vector<int> const& stack) const
+ {
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
+ }
+ }
+
+ void program::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << "local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ std::cout << "op_neg" << std::endl;
+ break;
+
+ case op_add:
+ std::cout << "op_add" << std::endl;
+ break;
+
+ case op_sub:
+ std::cout << "op_sub" << std::endl;
+ break;
+
+ case op_mul:
+ std::cout << "op_mul" << std::endl;
+ break;
+
+ case op_div:
+ std::cout << "op_div" << std::endl;
+ break;
+
+ case op_load:
+ std::cout << "op_load " << locals[*pc++] << std::endl;
+ break;
+
+ case op_store:
+ std::cout << "op_store " << locals[*pc++] << std::endl;
+ break;
+
+ case op_int:
+ std::cout << "op_int " << *pc++ << std::endl;
+ break;
+
+ case op_stk_adj:
+ std::cout << "op_stk_adj " << *pc++ << std::endl;
+ break;
+ }
+ }
+ }
+
+ bool compiler::operator()(unsigned int x) const
+ {
+ program.op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable const& x) const
+ {
+ int const* p = program.find_var(x.name);
+ if (p == 0)
+ {
+ std::cout << x.id << std::endl;
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ program.op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::operation const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case '+': program.op(op_add); break;
+ case '-': program.op(op_sub); break;
+ case '*': program.op(op_mul); break;
+ case '/': program.op(op_div); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::signed_ const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.sign)
+ {
+ case '-': program.op(op_neg); break;
+ case '+': break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ BOOST_FOREACH(ast::operation const& oper, x.rest)
+ {
+ if (!(*this)(oper))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x) const
+ {
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = program.find_var(x.lhs.name);
+ if (p == 0)
+ {
+ std::cout << x.lhs.id << std::endl;
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ program.op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x) const
+ {
+ int const* p = program.find_var(x.assign.lhs.name);
+ if (p != 0)
+ {
+ std::cout << x.assign.lhs.id << std::endl;
+ error_handler(x.assign.lhs.id, "Duplicate variable: " + x.assign.lhs.name);
+ return false;
+ }
+ bool r = (*this)(x.assign.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ program.add_var(x.assign.lhs.name);
+ program.op(op_store, *program.find_var(x.assign.lhs.name));
+ }
+ return r;
+ }
+
+ bool compiler::operator()(ast::statement_list const& x) const
+ {
+ program.clear();
+
+ // op_stk_adj 0 for now. we'll know how many variables we'll have later
+ program.op(op_stk_adj, 0);
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!boost::apply_visitor(*this, s))
+ {
+ program.clear();
+ return false;
+ }
+ }
+ program[1] = program.nvars(); // now store the actual number of variables
+ return true;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp
new file mode 100644
index 00000000..179a315a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp
@@ -0,0 +1,85 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_COMPILER_HPP)
+#define BOOST_SPIRIT_CALC7_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Program
+ ///////////////////////////////////////////////////////////////////////////
+ struct program
+ {
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[i]; }
+ int const& operator[](std::size_t i) const { return code[i]; }
+ void clear() { code.clear(); variables.clear(); }
+ std::vector<int> const& operator()() const { return code; }
+
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+
+ void print_variables(std::vector<int> const& stack) const;
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::vector<int> code;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(client::code_gen::program& program, ErrorHandler& error_handler_)
+ : program(program)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) const { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x) const;
+ bool operator()(ast::variable const& x) const;
+ bool operator()(ast::operation const& x) const;
+ bool operator()(ast::signed_ const& x) const;
+ bool operator()(ast::expression const& x) const;
+ bool operator()(ast::assignment const& x) const;
+ bool operator()(ast::variable_declaration const& x) const;
+ bool operator()(ast::statement_list const& x) const;
+
+ client::code_gen::program& program;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp
new file mode 100644
index 00000000..867e9ee7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp
@@ -0,0 +1,93 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CALC7_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ if (err_pos != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.cpp
new file mode 100644
index 00000000..32f44adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::expression<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp
new file mode 100644
index 00000000..916e26e7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp
@@ -0,0 +1,53 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CALC7_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct expression : qi::grammar<Iterator, ast::expression(), ascii::space_type>
+ {
+ expression(error_handler<Iterator>& error_handler);
+
+ qi::rule<Iterator, ast::expression(), ascii::space_type> expr;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> additive_expr;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> multiplicative_expr;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> unary_expr;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> primary_expr;
+ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp
new file mode 100644
index 00000000..2770677c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp
@@ -0,0 +1,94 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
+ : expression::base_type(expr)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ expr =
+ additive_expr.alias()
+ ;
+
+ additive_expr =
+ multiplicative_expr
+ >> *( (char_('+') > multiplicative_expr)
+ | (char_('-') > multiplicative_expr)
+ )
+ ;
+
+ multiplicative_expr =
+ unary_expr
+ >> *( (char_('*') > unary_expr)
+ | (char_('/') > unary_expr)
+ )
+ ;
+
+ unary_expr =
+ primary_expr
+ | (char_('-') > primary_expr)
+ | (char_('+') > primary_expr)
+ ;
+
+ primary_expr =
+ uint_
+ | identifier
+ | '(' > expr > ')'
+ ;
+
+ identifier =
+ raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (additive_expr)
+ (multiplicative_expr)
+ (unary_expr)
+ (primary_expr)
+ (identifier)
+ );
+
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp
new file mode 100644
index 00000000..4e139eb2
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp
@@ -0,0 +1,101 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Now we'll introduce variables and assignment. This time, we'll also
+// be renaming some of the rules -- a strategy for a grander scheme
+// to come ;-)
+//
+// This version also shows off grammar modularization. Here you will
+// see how expressions and statements are built as modular grammars.
+//
+// [ JDG April 9, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "statement.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Statement parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type some statements... ";
+ std::cout << "An empty line ends input, compiles, runs and prints results\n\n";
+ std::cout << "Example:\n\n";
+ std::cout << " var a = 123;\n";
+ std::cout << " var b = 456;\n";
+ std::cout << " var c = a + b * 2;\n\n";
+ std::cout << "-------------------------\n";
+
+ std::string str;
+ std::string source;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+ source += str + '\n';
+ }
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source.begin();
+ iterator_type end = source.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::code_gen::program program; // Our VM program
+ client::ast::statement_list ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::parser::statement<iterator_type>
+ parser(error_handler); // Our parser
+ client::code_gen::compiler
+ compile(program, error_handler); // Our compiler
+
+ boost::spirit::ascii::space_type space;
+ bool success = phrase_parse(iter, end, parser, space, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compile(ast))
+ {
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ vm.execute(program());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ program.print_assembler();
+
+ std::cout << "-------------------------\n";
+ std::cout << "Results------------------\n\n";
+ program.print_variables(vm.get_stack());
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+
+ std::cout << "-------------------------\n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp
new file mode 100644
index 00000000..54bc9ac3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::statement<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp
new file mode 100644
index 00000000..12baf38f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_STATEMENT_HPP)
+#define BOOST_SPIRIT_CALC7_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement_list(), ascii::space_type>
+ {
+ statement(error_handler<Iterator>& error_handler);
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement_list(), ascii::space_type> statement_list;
+ qi::rule<Iterator, ast::variable_declaration(), ascii::space_type> variable_declaration;
+ qi::rule<Iterator, ast::assignment(), ascii::space_type> assignment;
+ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp
new file mode 100644
index 00000000..408a2368
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp
@@ -0,0 +1,75 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(statement_list), expr(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +(variable_declaration | assignment)
+ ;
+
+ identifier =
+ raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ lexeme["var" >> !(alnum | '_')] // make sure we have whole words
+ > assignment
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (identifier)
+ (variable_declaration)
+ (assignment)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in assignment, call annotation.
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.cpp
new file mode 100644
index 00000000..c481f2b7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.cpp
@@ -0,0 +1,66 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "vm.hpp"
+
+namespace client
+{
+ void vmachine::execute(std::vector<int> const& code)
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+ std::vector<int>::iterator locals = stack.begin();
+ stack_ptr = stack.begin();
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_load:
+ *stack_ptr++ = locals[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ locals[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_stk_adj:
+ stack_ptr = stack.begin() + *pc++;
+ break;
+ }
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp
new file mode 100644
index 00000000..853aa9c7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp
@@ -0,0 +1,52 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_VM_HPP)
+#define BOOST_SPIRIT_CALC7_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+ op_int, // push constant integer into the stack
+ op_stk_adj // adjust the stack for local variables
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ void execute(std::vector<int> const& code);
+ std::vector<int> const& get_stack() const { return stack; };
+
+ private:
+
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/annotation.hpp
new file mode 100644
index 00000000..8cd00973
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/annotation.hpp
@@ -0,0 +1,78 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CALC8_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ this->dispatch(x, boost::is_base_of<ast::tagged, T>());
+ }
+
+ // This will catch all nodes except those inheriting from ast::tagged
+ template <typename T>
+ void dispatch(T& x, boost::mpl::false_) const
+ {
+ // (no-op) no need for tags
+ }
+
+ // This will catch all nodes inheriting from ast::tagged
+ template <typename T>
+ void dispatch(T& x, boost::mpl::true_) const
+ {
+ x.id = id;
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/ast.hpp
new file mode 100644
index 00000000..3e6e2d79
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/ast.hpp
@@ -0,0 +1,172 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_AST_HPP)
+#define BOOST_SPIRIT_CALC8_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct expression;
+
+ struct variable : tagged
+ {
+ variable(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , variable
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ enum optoken
+ {
+ op_plus,
+ op_minus,
+ op_times,
+ op_divide,
+ op_positive,
+ op_negative,
+ op_not,
+ op_equal,
+ op_not_equal,
+ op_less,
+ op_less_equal,
+ op_greater,
+ op_greater_equal,
+ op_and,
+ op_or
+ };
+
+ struct unary
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ variable lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ assignment assign;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+ inline std::ostream& operator<<(std::ostream& out, variable const& var) { out << var.name; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::assignment, assign)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::variable, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp
new file mode 100644
index 00000000..2d8b3eb1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp
@@ -0,0 +1,382 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void program::op(int a)
+ {
+ code.push_back(a);
+ }
+
+ void program::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ }
+
+ void program::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ }
+
+ int const* program::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void program::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void program::print_variables(std::vector<int> const& stack) const
+ {
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
+ }
+ }
+
+ void program::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << " local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != code.end())
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ typedef std::pair<std::size_t, std::string> line_info;
+ BOOST_FOREACH(line_info const& l, lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x) const
+ {
+ program.op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x) const
+ {
+ program.op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable const& x) const
+ {
+ int const* p = program.find_var(x.name);
+ if (p == 0)
+ {
+ std::cout << x.id << std::endl;
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ program.op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::operation const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_plus: program.op(op_add); break;
+ case ast::op_minus: program.op(op_sub); break;
+ case ast::op_times: program.op(op_mul); break;
+ case ast::op_divide: program.op(op_div); break;
+
+ case ast::op_equal: program.op(op_eq); break;
+ case ast::op_not_equal: program.op(op_neq); break;
+ case ast::op_less: program.op(op_lt); break;
+ case ast::op_less_equal: program.op(op_lte); break;
+ case ast::op_greater: program.op(op_gt); break;
+ case ast::op_greater_equal: program.op(op_gte); break;
+
+ case ast::op_and: program.op(op_and); break;
+ case ast::op_or: program.op(op_or); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_negative: program.op(op_neg); break;
+ case ast::op_not: program.op(op_not); break;
+ case ast::op_positive: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ BOOST_FOREACH(ast::operation const& oper, x.rest)
+ {
+ if (!(*this)(oper))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x) const
+ {
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = program.find_var(x.lhs.name);
+ if (p == 0)
+ {
+ std::cout << x.lhs.id << std::endl;
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ program.op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x) const
+ {
+ int const* p = program.find_var(x.assign.lhs.name);
+ if (p != 0)
+ {
+ std::cout << x.assign.lhs.id << std::endl;
+ error_handler(x.assign.lhs.id, "Duplicate variable: " + x.assign.lhs.name);
+ return false;
+ }
+ bool r = (*this)(x.assign.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ program.add_var(x.assign.lhs.name);
+ program.op(op_store, *program.find_var(x.assign.lhs.name));
+ }
+ return r;
+ }
+
+ bool compiler::operator()(ast::statement const& x) const
+ {
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x) const
+ {
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x) const
+ {
+ if (!(*this)(x.condition))
+ return false;
+ program.op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = program.size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ program[skip] = program.size()-skip; // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an alse
+ {
+ program[skip] += 2; // adjust for the "else" jump
+ program.op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = program.size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ program[exit] = program.size()-exit; // now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x) const
+ {
+ std::size_t loop = program.size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ program.op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = program.size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ program.op(op_jump,
+ int(loop-1) - int(program.size())); // loop back
+ program[exit] = program.size()-exit; // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::start(ast::statement_list const& x) const
+ {
+ program.clear();
+ // op_stk_adj 0 for now. we'll know how many variables we'll have later
+ program.op(op_stk_adj, 0);
+
+ if (!(*this)(x))
+ {
+ program.clear();
+ return false;
+ }
+ program[1] = program.nvars(); // now store the actual number of variables
+ return true;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.hpp
new file mode 100644
index 00000000..915a87d0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.hpp
@@ -0,0 +1,92 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_COMPILER_HPP)
+#define BOOST_SPIRIT_CALC8_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Program
+ ///////////////////////////////////////////////////////////////////////////
+ struct program
+ {
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[i]; }
+ int const& operator[](std::size_t i) const { return code[i]; }
+ void clear() { code.clear(); variables.clear(); }
+ std::size_t size() const { return code.size(); }
+ std::vector<int> const& operator()() const { return code; }
+
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+
+ void print_variables(std::vector<int> const& stack) const;
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::vector<int> code;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(client::code_gen::program& program, ErrorHandler& error_handler_)
+ : program(program)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) const { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x) const;
+ bool operator()(bool x) const;
+ bool operator()(ast::variable const& x) const;
+ bool operator()(ast::operation const& x) const;
+ bool operator()(ast::unary const& x) const;
+ bool operator()(ast::expression const& x) const;
+ bool operator()(ast::assignment const& x) const;
+ bool operator()(ast::variable_declaration const& x) const;
+ bool operator()(ast::statement_list const& x) const;
+ bool operator()(ast::statement const& x) const;
+ bool operator()(ast::if_statement const& x) const;
+ bool operator()(ast::while_statement const& x) const;
+
+ bool start(ast::statement_list const& x) const;
+
+ client::code_gen::program& program;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/error_handler.hpp
new file mode 100644
index 00000000..0cc42ca9
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/error_handler.hpp
@@ -0,0 +1,93 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CALC8_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ if (err_pos != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.cpp
new file mode 100644
index 00000000..32f44adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::expression<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.hpp
new file mode 100644
index 00000000..e5770bb1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.hpp
@@ -0,0 +1,68 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CALC8_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct expression : qi::grammar<Iterator, ast::expression(), ascii::space_type>
+ {
+ expression(error_handler<Iterator>& error_handler);
+
+ qi::rule<Iterator, ast::expression(), ascii::space_type>
+ expr, equality_expr, relational_expr,
+ logical_expr, additive_expr, multiplicative_expr
+ ;
+
+ qi::rule<Iterator, ast::operand(), ascii::space_type>
+ unary_expr, primary_expr
+ ;
+
+ qi::rule<Iterator, std::string(), ascii::space_type>
+ identifier
+ ;
+
+ qi::symbols<char, ast::optoken>
+ equality_op, relational_op, logical_op,
+ additive_op, multiplicative_op, unary_op
+ ;
+
+ qi::symbols<char>
+ keywords
+ ;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression_def.hpp
new file mode 100644
index 00000000..608992c3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression_def.hpp
@@ -0,0 +1,159 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
+ : expression::base_type(expr)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::bool_type bool_;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tokens
+ logical_op.add
+ ("&&", ast::op_and)
+ ("||", ast::op_or)
+ ;
+
+ equality_op.add
+ ("==", ast::op_equal)
+ ("!=", ast::op_not_equal)
+ ;
+
+ relational_op.add
+ ("<", ast::op_less)
+ ("<=", ast::op_less_equal)
+ (">", ast::op_greater)
+ (">=", ast::op_greater_equal)
+ ;
+
+ additive_op.add
+ ("+", ast::op_plus)
+ ("-", ast::op_minus)
+ ;
+
+ multiplicative_op.add
+ ("*", ast::op_times)
+ ("/", ast::op_divide)
+ ;
+
+ unary_op.add
+ ("+", ast::op_positive)
+ ("-", ast::op_negative)
+ ("!", ast::op_not)
+ ;
+
+ keywords.add
+ ("var")
+ ("true")
+ ("false")
+ ("if")
+ ("else")
+ ("while")
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ logical_expr.alias()
+ ;
+
+ logical_expr =
+ equality_expr
+ >> *(logical_op > equality_expr)
+ ;
+
+ equality_expr =
+ relational_expr
+ >> *(equality_op > relational_expr)
+ ;
+
+ relational_expr =
+ additive_expr
+ >> *(relational_op > additive_expr)
+ ;
+
+ additive_expr =
+ multiplicative_expr
+ >> *(additive_op > multiplicative_expr)
+ ;
+
+ multiplicative_expr =
+ unary_expr
+ >> *(multiplicative_op > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (unary_op > primary_expr)
+ ;
+
+ primary_expr =
+ uint_
+ | identifier
+ | bool_
+ | '(' > expr > ')'
+ ;
+
+ identifier =
+ !keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (equality_expr)
+ (relational_expr)
+ (logical_expr)
+ (additive_expr)
+ (multiplicative_expr)
+ (unary_expr)
+ (primary_expr)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/main.cpp
new file mode 100644
index 00000000..9c3b7346
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/main.cpp
@@ -0,0 +1,97 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Now we'll introduce boolean expressions and control structures.
+// Is it obvious now what we are up to? ;-)
+//
+// [ JDG April 9, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "statement.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Statement parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type some statements... ";
+ std::cout << "An empty line ends input, compiles, runs and prints results\n\n";
+ std::cout << "Example:\n\n";
+ std::cout << " var a = 123;\n";
+ std::cout << " var b = 456;\n";
+ std::cout << " var c = a + b * 2;\n\n";
+ std::cout << "-------------------------\n";
+
+ std::string str;
+ std::string source;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+ source += str + '\n';
+ }
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source.begin();
+ iterator_type end = source.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::code_gen::program program; // Our VM program
+ client::ast::statement_list ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::parser::statement<iterator_type>
+ parser(error_handler); // Our parser
+ client::code_gen::compiler
+ compile(program, error_handler); // Our compiler
+
+ boost::spirit::ascii::space_type space;
+ bool success = phrase_parse(iter, end, parser, space, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compile.start(ast))
+ {
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ vm.execute(program());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ program.print_assembler();
+
+ std::cout << "-------------------------\n";
+ std::cout << "Results------------------\n\n";
+ program.print_variables(vm.stack);
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+
+ std::cout << "-------------------------\n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.cpp
new file mode 100644
index 00000000..54bc9ac3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::statement<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.hpp
new file mode 100644
index 00000000..8b6c6b77
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.hpp
@@ -0,0 +1,37 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_STATEMENT_HPP)
+#define BOOST_SPIRIT_CALC8_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement_list(), ascii::space_type>
+ {
+ statement(error_handler<Iterator>& error_handler);
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement_list(), ascii::space_type>
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement(), ascii::space_type> statement_;
+ qi::rule<Iterator, ast::variable_declaration(), ascii::space_type> variable_declaration;
+ qi::rule<Iterator, ast::assignment(), ascii::space_type> assignment;
+ qi::rule<Iterator, ast::if_statement(), ascii::space_type> if_statement;
+ qi::rule<Iterator, ast::while_statement(), ascii::space_type> while_statement;
+ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement_def.hpp
new file mode 100644
index 00000000..d007ac06
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement_def.hpp
@@ -0,0 +1,111 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(statement_list), expr(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::lit_type lit;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ ;
+
+ identifier =
+ !expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ lexeme["var" >> !(alnum | '_')] // make sure we have whole words
+ > &identifier // expect an identifier
+ > assignment
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ lit("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ lexeme["else" >> !(alnum | '_')] // make sure we have whole words
+ > statement_
+ )
+ ;
+
+ while_statement =
+ lit("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (identifier)
+ (variable_declaration)
+ (assignment)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in assignment, call annotation.
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp
new file mode 100644
index 00000000..70589fa1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp
@@ -0,0 +1,163 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "vm.hpp"
+#include <boost/assert.hpp>
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (pc != code.end())
+ {
+ BOOST_ASSERT(pc != code.end());
+
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr = stack.begin() + *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ return -1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.hpp
new file mode 100644
index 00000000..bab387f7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.hpp
@@ -0,0 +1,77 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_VM_HPP)
+#define BOOST_SPIRIT_CALC8_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ };
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/annotation.hpp
new file mode 100644
index 00000000..2361a7f4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/annotation.hpp
@@ -0,0 +1,95 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CONJURE_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ void operator()(ast::identifier& x) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ // no-op
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::variable_declaration& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/ast.hpp
new file mode 100644
index 00000000..e5022472
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/ast.hpp
@@ -0,0 +1,275 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_AST_HPP)
+#define BOOST_SPIRIT_CONJURE_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<function_call>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ enum optoken
+ {
+ // precedence 1
+ op_comma,
+
+ // precedence 2
+ op_assign,
+ op_plus_assign,
+ op_minus_assign,
+ op_times_assign,
+ op_divide_assign,
+ op_mod_assign,
+ op_bit_and_assign,
+ op_bit_xor_assign,
+ op_bitor_assign,
+ op_shift_left_assign,
+ op_shift_right_assign,
+
+ // precedence 3
+ op_logical_or,
+
+ // precedence 4
+ op_logical_and,
+
+ // precedence 5
+ op_bit_or,
+
+ // precedence 6
+ op_bit_xor,
+
+ // precedence 7
+ op_bit_and,
+
+ // precedence 8
+ op_equal,
+ op_not_equal,
+
+ // precedence 9
+ op_less,
+ op_less_equal,
+ op_greater,
+ op_greater_equal,
+
+ // precedence 10
+ op_shift_left,
+ op_shift_right,
+
+ // precedence 11
+ op_plus,
+ op_minus,
+
+ // precedence 12
+ op_times,
+ op_divide,
+ op_mod,
+
+ // precedence 13
+ op_positive,
+ op_negative,
+ op_pre_incr,
+ op_pre_decr,
+ op_compl,
+ op_not,
+
+ // precedence 14
+ op_post_incr,
+ op_post_decr,
+ };
+
+ struct unary
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ statement_list body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (client::ast::statement_list, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.cpp
new file mode 100644
index 00000000..22a036d4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.cpp
@@ -0,0 +1,628 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void function::op(int a)
+ {
+ code.push_back(a);
+ size_ += 1;
+ }
+
+ void function::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ size_ += 2;
+ }
+
+ void function::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ size_ += 3;
+ }
+
+ int const* function::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void function::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void function::link_to(std::string const& name, std::size_t address)
+ {
+ function_calls[address] = name;
+ }
+
+ void function::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin() + address;
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << " local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != (code.begin() + address + size_))
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_call:
+ {
+ line += " op_call ";
+ int nargs = *pc++;
+ std::size_t jump = *pc++;
+ line += boost::lexical_cast<std::string>(nargs) + ", ";
+ BOOST_ASSERT(function_calls.find(jump) != function_calls.end());
+ line += function_calls.find(jump)->second;
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+
+ case op_return:
+ line += " op_return";
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ typedef std::pair<std::size_t, std::string> line_info;
+ BOOST_FOREACH(line_info const& l, lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::identifier const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.name);
+ if (p == 0)
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ current->op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::optoken const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ switch (x)
+ {
+ case ast::op_plus: current->op(op_add); break;
+ case ast::op_minus: current->op(op_sub); break;
+ case ast::op_times: current->op(op_mul); break;
+ case ast::op_divide: current->op(op_div); break;
+
+ case ast::op_equal: current->op(op_eq); break;
+ case ast::op_not_equal: current->op(op_neq); break;
+ case ast::op_less: current->op(op_lt); break;
+ case ast::op_less_equal: current->op(op_lte); break;
+ case ast::op_greater: current->op(op_gt); break;
+ case ast::op_greater_equal: current->op(op_gte); break;
+
+ case ast::op_logical_or: current->op(op_or); break;
+ case ast::op_logical_and: current->op(op_and); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_negative: current->op(op_neg); break;
+ case ast::op_not: current->op(op_not); break;
+ case ast::op_positive: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_call const& x)
+ {
+ BOOST_ASSERT(current != 0);
+
+ if (functions.find(x.function_name.name) == functions.end())
+ {
+ error_handler(x.function_name.id, "Function not found: " + x.function_name.name);
+ return false;
+ }
+
+ boost::shared_ptr<code_gen::function> p = functions[x.function_name.name];
+
+ if (p->nargs() != x.args.size())
+ {
+ error_handler(x.function_name.id, "Wrong number of arguments: " + x.function_name.name);
+ return false;
+ }
+
+ BOOST_FOREACH(ast::expression const& expr, x.args)
+ {
+ if (!(*this)(expr))
+ return false;
+ }
+
+ current->op(
+ op_call,
+ p->nargs(),
+ p->get_address());
+ current->link_to(x.function_name.name, p->get_address());
+
+ return true;
+ }
+
+ namespace
+ {
+ int precedence[] = {
+ // precedence 1
+ 1, // op_comma
+
+ // precedence 2
+ 2, // op_assign
+ 2, // op_plus_assign
+ 2, // op_minus_assign
+ 2, // op_times_assign
+ 2, // op_divide_assign
+ 2, // op_mod_assign
+ 2, // op_bit_and_assign
+ 2, // op_bit_xor_assign
+ 2, // op_bitor_assign
+ 2, // op_shift_left_assign
+ 2, // op_shift_right_assign
+
+ // precedence 3
+ 3, // op_logical_or
+
+ // precedence 4
+ 4, // op_logical_and
+
+ // precedence 5
+ 5, // op_bit_or
+
+ // precedence 6
+ 6, // op_bit_xor
+
+ // precedence 7
+ 7, // op_bit_and
+
+ // precedence 8
+ 8, // op_equal
+ 8, // op_not_equal
+
+ // precedence 9
+ 9, // op_less
+ 9, // op_less_equal
+ 9, // op_greater
+ 9, // op_greater_equal
+
+ // precedence 10
+ 10, // op_shift_left
+ 10, // op_shift_right
+
+ // precedence 11
+ 11, // op_plus
+ 11, // op_minus
+
+ // precedence 12
+ 12, // op_times
+ 12, // op_divide
+ 12, // op_mod
+
+ // precedence 13
+ 13, // op_positive
+ 13, // op_negative
+ 13, // op_pre_incr
+ 13, // op_pre_decr
+ 13, // op_compl
+ 13, // op_not
+
+ // precedence 14
+ 14, // op_post_incr
+ 14 // op_post_decr
+ };
+ }
+
+ // The Shunting-yard algorithm
+ bool compiler::compile_expression(
+ int min_precedence,
+ std::list<ast::operation>::const_iterator& rbegin,
+ std::list<ast::operation>::const_iterator rend)
+ {
+ while ((rbegin != rend) && (precedence[rbegin->operator_] >= min_precedence))
+ {
+ ast::optoken op = rbegin->operator_;
+ if (!boost::apply_visitor(*this, rbegin->operand_))
+ return false;
+ ++rbegin;
+
+ while ((rbegin != rend) && (precedence[rbegin->operator_] > precedence[op]))
+ {
+ ast::optoken next_op = rbegin->operator_;
+ compile_expression(precedence[next_op], rbegin, rend);
+ }
+ (*this)(op);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ std::list<ast::operation>::const_iterator rbegin = x.rest.begin();
+ if (!compile_expression(0, rbegin, x.rest.end()))
+ return false;
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = current->find_var(x.lhs.name);
+ if (p == 0)
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ current->op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.lhs.name);
+ if (p != 0)
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+ if (x.rhs) // if there's an RHS initializer
+ {
+ bool r = (*this)(*x.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ current->add_var(x.lhs.name);
+ current->op(op_store, *current->find_var(x.lhs.name));
+ }
+ return r;
+ }
+ else
+ {
+ current->add_var(x.lhs.name);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = current->size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ (*current)[skip] = current->size()-skip; // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an alse
+ {
+ (*current)[skip] += 2; // adjust for the "else" jump
+ current->op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ (*current)[exit] = current->size()-exit;// now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ std::size_t loop = current->size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ current->op(op_jump,
+ int(loop-1) - int(current->size())); // loop back
+ (*current)[exit] = current->size()-exit; // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(x.id, current_function_name + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ if (!(*this)(*x.expr))
+ return false;
+ }
+ current->op(op_return);
+ return true;
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ if (functions.find(x.function_name.name) != functions.end())
+ {
+ error_handler(x.function_name.id, "Duplicate function: " + x.function_name.name);
+ return false;
+ }
+ boost::shared_ptr<code_gen::function>& p = functions[x.function_name.name];
+ p.reset(new code_gen::function(code, x.args.size()));
+ current = p.get();
+ current_function_name = x.function_name.name;
+
+ // op_stk_adj 0 for now. we'll know how many variables
+ // we'll have later and add them
+ current->op(op_stk_adj, 0);
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ current->add_var(arg.name);
+ }
+
+ if (!(*this)(x.body))
+ return false;
+ (*current)[1] = current->nvars(); // now store the actual number of variables
+ // this includes the arguments
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ // Jump to the main function
+ code.push_back(op_jump);
+ code.push_back(0); // we will fill this in later when we finish compiling
+ // and we know where the main function is
+
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ if (!(*this)(f))
+ {
+ code.clear();
+ return false;
+ }
+ }
+ // find the main function
+ boost::shared_ptr<code_gen::function> p =
+ find_function("main");
+
+ if (!p) // main function not found
+ {
+ std::cerr << "Error: main function not defined" << std::endl;
+ return false;
+ }
+ code[1] = p->get_address()-1; // jump to this (main function) address
+
+ return true;
+ }
+
+ void compiler::print_assembler() const
+ {
+ typedef std::pair<std::string, boost::shared_ptr<code_gen::function> > pair;
+ BOOST_FOREACH(pair const& p, functions)
+ {
+ std::cout << ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" << std::endl;
+ std::cout << p.second->get_address() << ": function " << p.first << std::endl;
+ p.second->print_assembler();
+ }
+ }
+
+ boost::shared_ptr<code_gen::function>
+ compiler::find_function(std::string const& name) const
+ {
+ function_table::const_iterator i = functions.find(name);
+ if (i == functions.end())
+ return boost::shared_ptr<code_gen::function>();
+ else
+ return i->second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.hpp
new file mode 100644
index 00000000..461f7a7c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.hpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP)
+#define BOOST_SPIRIT_CONJURE_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Function
+ ///////////////////////////////////////////////////////////////////////////
+ struct function
+ {
+ function(std::vector<int>& code, int nargs)
+ : code(code), address(code.size()), size_(0), nargs_(nargs) {}
+
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[address+i]; }
+ int const& operator[](std::size_t i) const { return code[address+i]; }
+ std::size_t size() const { return size_; }
+ std::size_t get_address() const { return address; }
+
+ int nargs() const { return nargs_; }
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+ void link_to(std::string const& name, std::size_t address);
+
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::map<std::size_t, std::string> function_calls;
+ std::vector<int>& code;
+ std::size_t address;
+ std::size_t size_;
+ std::size_t nargs_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(ErrorHandler& error_handler_)
+ : current(0)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x);
+ bool operator()(bool x);
+ bool operator()(ast::identifier const& x);
+ bool operator()(ast::optoken const& x);
+ bool operator()(ast::unary const& x);
+ bool operator()(ast::function_call const& x);
+ bool operator()(ast::expression const& x);
+ bool operator()(ast::assignment const& x);
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ void print_assembler() const;
+
+ boost::shared_ptr<code_gen::function>
+ find_function(std::string const& name) const;
+
+ std::vector<int>& get_code() { return code; }
+ std::vector<int> const& get_code() const { return code; }
+
+ private:
+
+ bool compile_expression(
+ int min_precedence,
+ std::list<ast::operation>::const_iterator& rbegin,
+ std::list<ast::operation>::const_iterator rend);
+
+ typedef std::map<std::string, boost::shared_ptr<code_gen::function> > function_table;
+
+ std::vector<int> code;
+ code_gen::function* current;
+ std::string current_function_name;
+ function_table functions;
+ bool void_return;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/error_handler.hpp
new file mode 100644
index 00000000..2c1aa44e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/error_handler.hpp
@@ -0,0 +1,93 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ if (err_pos != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.cpp
new file mode 100644
index 00000000..32f44adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::expression<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.hpp
new file mode 100644
index 00000000..985b972c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.hpp
@@ -0,0 +1,75 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CONJURE_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include "skipper.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct expression : qi::grammar<Iterator, ast::expression(), skipper<Iterator> >
+ {
+ expression(error_handler<Iterator>& error_handler);
+
+ qi::rule<Iterator, ast::expression(), skipper<Iterator> >
+ expr
+ ;
+
+ qi::rule<Iterator, ast::operand(), skipper<Iterator> >
+ unary_expr, primary_expr
+ ;
+
+ qi::rule<Iterator, ast::function_call(), skipper<Iterator> >
+ function_call
+ ;
+
+ qi::rule<Iterator, std::list<ast::expression>(), skipper<Iterator> >
+ argument_list
+ ;
+
+ qi::rule<Iterator, std::string(), skipper<Iterator> >
+ identifier
+ ;
+
+ qi::symbols<char, ast::optoken>
+ unary_op, binary_op
+ ;
+
+ qi::symbols<char>
+ keywords
+ ;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression_def.hpp
new file mode 100644
index 00000000..21ccc9bd
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression_def.hpp
@@ -0,0 +1,131 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
+ : expression::base_type(expr)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::bool_type bool_;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tokens
+ binary_op.add
+ ("||", ast::op_logical_or)
+ ("&&", ast::op_logical_and)
+ ("==", ast::op_equal)
+ ("!=", ast::op_not_equal)
+ ("<", ast::op_less)
+ ("<=", ast::op_less_equal)
+ (">", ast::op_greater)
+ (">=", ast::op_greater_equal)
+ ("+", ast::op_plus)
+ ("-", ast::op_minus)
+ ("*", ast::op_times)
+ ("/", ast::op_divide)
+ ;
+
+ unary_op.add
+ ("+", ast::op_positive)
+ ("-", ast::op_negative)
+ ("!", ast::op_not)
+ ;
+
+ keywords.add
+ ("true")
+ ("false")
+ ("if")
+ ("else")
+ ("while")
+ ("int")
+ ("void")
+ ("return")
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ unary_expr
+ >> *(binary_op > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (unary_op > unary_expr)
+ ;
+
+ primary_expr =
+ uint_
+ | function_call
+ | identifier
+ | bool_
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier =
+ !lexeme[keywords >> !(alnum | '_')]
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (unary_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.cpp
new file mode 100644
index 00000000..ababd4ad
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "function_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::function<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.hpp
new file mode 100644
index 00000000..9eddd66c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_FUNCTION_HPP)
+#define BOOST_SPIRIT_CONJURE_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct function : qi::grammar<Iterator, ast::function(), skipper<Iterator> >
+ {
+ function(error_handler<Iterator>& error_handler);
+
+ statement<Iterator> body;
+ qi::rule<Iterator, std::string(), skipper<Iterator> > name;
+ qi::rule<Iterator, ast::identifier(), skipper<Iterator> > identifier;
+ qi::rule<Iterator, std::list<ast::identifier>(), skipper<Iterator> > argument_list;
+ qi::rule<Iterator, ast::function(), skipper<Iterator> > start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function_def.hpp
new file mode 100644
index 00000000..bd2c7d02
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function_def.hpp
@@ -0,0 +1,71 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ function<Iterator>::function(error_handler<Iterator>& error_handler)
+ : function::base_type(start), body(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::string_type string;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ name =
+ !body.expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ identifier = name;
+ argument_list = -(identifier % ',');
+
+ start =
+ lexeme[(string("void") | string("int"))
+ >> !(alnum | '_')] // make sure we have whole words
+ > identifier
+ > '(' > argument_list > ')'
+ > '{' > body > '}'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/main.cpp
new file mode 100644
index 00000000..8b2a8007
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/main.cpp
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "function.hpp"
+#include "skipper.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source_code.begin();
+ iterator_type end = source_code.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::parser::function<iterator_type>
+ function(error_handler); // Our parser
+ client::parser::skipper<iterator_type>
+ skipper; // Our skipper
+ client::code_gen::compiler
+ compiler(error_handler); // Our compiler
+
+
+ bool success = phrase_parse(iter, end, +function, skipper, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ boost::shared_ptr<client::code_gen::function>
+ p = compiler.find_function("main");
+ if (!p)
+ return 1;
+
+ int nargs = argc-2;
+ if (p->nargs() != nargs)
+ {
+ std::cerr << "Error: main function requires " << p->nargs() << " arguments." << std::endl;
+ std::cerr << nargs << " supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ compiler.print_assembler();
+
+ // Push the arguments into our stack
+ for (int i = 0; i < nargs; ++i)
+ vm.get_stack()[i] = boost::lexical_cast<int>(argv[i+2]);
+
+ // Call the interpreter
+ int r = vm.execute(compiler.get_code());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/skipper.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/skipper.hpp
new file mode 100644
index 00000000..bb1acc21
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/skipper.hpp
@@ -0,0 +1,40 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_SKIPPER_HPP)
+#define BOOST_SPIRIT_CONJURE_SKIPPER_HPP
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The skipper grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct skipper : qi::grammar<Iterator>
+ {
+ skipper() : skipper::base_type(start)
+ {
+ qi::char_type char_;
+ ascii::space_type space;
+
+ start =
+ space // tab/space/cr/lf
+ | "/*" >> *(char_ - "*/") >> "*/" // C-style comments
+ ;
+ }
+
+ qi::rule<Iterator> start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.cpp
new file mode 100644
index 00000000..54bc9ac3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::statement<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.hpp
new file mode 100644
index 00000000..72485cbf
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.hpp
@@ -0,0 +1,38 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_STATEMENT_HPP)
+#define BOOST_SPIRIT_CONJURE_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement_list(), skipper<Iterator> >
+ {
+ statement(error_handler<Iterator>& error_handler);
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement_list(), skipper<Iterator> >
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement(), skipper<Iterator> > statement_;
+ qi::rule<Iterator, ast::variable_declaration(), skipper<Iterator> > variable_declaration;
+ qi::rule<Iterator, ast::assignment(), skipper<Iterator> > assignment;
+ qi::rule<Iterator, ast::if_statement(), skipper<Iterator> > if_statement;
+ qi::rule<Iterator, ast::while_statement(), skipper<Iterator> > while_statement;
+ qi::rule<Iterator, ast::return_statement(), skipper<Iterator> > return_statement;
+ qi::rule<Iterator, std::string(), skipper<Iterator> > identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement_def.hpp
new file mode 100644
index 00000000..29e40942
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement_def.hpp
@@ -0,0 +1,128 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(statement_list), expr(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::lit_type lit;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ ;
+
+ identifier =
+ !expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ lexeme["int" >> !(alnum | '_')] // make sure we have whole words
+ > identifier
+ > -('=' > expr)
+ > ';'
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ lit("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ lexeme["else" >> !(alnum | '_')] // make sure we have whole words
+ > statement_
+ )
+ ;
+
+ while_statement =
+ lit("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ lexeme["return" >> !(alnum | '_')] // make sure we have whole words
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (statement_)
+ (variable_declaration)
+ (assignment)
+ (if_statement)
+ (while_statement)
+ (compound_statement)
+ (return_statement)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in variable_declaration,
+ // assignment and return_statement, call annotation.
+ on_success(variable_declaration,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.cpp
new file mode 100644
index 00000000..8740bf9c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.cpp
@@ -0,0 +1,159 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "vm.hpp"
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (true)
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr += *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.hpp
new file mode 100644
index 00000000..0362eaf8
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.hpp
@@ -0,0 +1,82 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_VM_HPP)
+#define BOOST_SPIRIT_CONJURE_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ }
+
+ std::vector<int> const& get_stack() const { return stack; };
+ std::vector<int>& get_stack() { return stack; };
+
+ private:
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/annotation.hpp
new file mode 100644
index 00000000..2361a7f4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/annotation.hpp
@@ -0,0 +1,95 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CONJURE_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ void operator()(ast::identifier& x) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ // no-op
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::variable_declaration& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ast.hpp
new file mode 100644
index 00000000..d2f893b0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ast.hpp
@@ -0,0 +1,209 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_AST_HPP)
+#define BOOST_SPIRIT_CONJURE_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+#include "ids.hpp"
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<function_call>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ struct unary
+ {
+ token_ids::type operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ token_ids::type operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ statement_list body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::token_ids::type, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::token_ids::type, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (client::ast::statement_list, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.cpp
new file mode 100644
index 00000000..87459b35
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.cpp
@@ -0,0 +1,622 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "config.hpp"
+#include "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void function::op(int a)
+ {
+ code.push_back(a);
+ size_ += 1;
+ }
+
+ void function::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ size_ += 2;
+ }
+
+ void function::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ size_ += 3;
+ }
+
+ int const* function::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void function::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void function::link_to(std::string const& name, std::size_t address)
+ {
+ function_calls[address] = name;
+ }
+
+ void function::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin() + address;
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << " local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != (code.begin() + address + size_))
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_call:
+ {
+ line += " op_call ";
+ int nargs = *pc++;
+ std::size_t jump = *pc++;
+ line += boost::lexical_cast<std::string>(nargs) + ", ";
+ BOOST_ASSERT(function_calls.find(jump) != function_calls.end());
+ line += function_calls.find(jump)->second;
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+
+ case op_return:
+ line += " op_return";
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ typedef std::pair<std::size_t, std::string> line_info;
+ BOOST_FOREACH(line_info const& l, lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::identifier const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.name);
+ if (p == 0)
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ current->op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(token_ids::type const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ switch (x)
+ {
+ case token_ids::plus: current->op(op_add); break;
+ case token_ids::minus: current->op(op_sub); break;
+ case token_ids::times: current->op(op_mul); break;
+ case token_ids::divide: current->op(op_div); break;
+
+ case token_ids::equal: current->op(op_eq); break;
+ case token_ids::not_equal: current->op(op_neq); break;
+ case token_ids::less: current->op(op_lt); break;
+ case token_ids::less_equal: current->op(op_lte); break;
+ case token_ids::greater: current->op(op_gt); break;
+ case token_ids::greater_equal: current->op(op_gte); break;
+
+ case token_ids::logical_or: current->op(op_or); break;
+ case token_ids::logical_and: current->op(op_and); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case token_ids::minus: current->op(op_neg); break;
+ case token_ids::not_: current->op(op_not); break;
+ case token_ids::plus: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_call const& x)
+ {
+ BOOST_ASSERT(current != 0);
+
+ if (functions.find(x.function_name.name) == functions.end())
+ {
+ error_handler(x.function_name.id, "Function not found: " + x.function_name.name);
+ return false;
+ }
+
+ boost::shared_ptr<code_gen::function> p = functions[x.function_name.name];
+
+ if (p->nargs() != x.args.size())
+ {
+ error_handler(x.function_name.id, "Wrong number of arguments: " + x.function_name.name);
+ return false;
+ }
+
+ BOOST_FOREACH(ast::expression const& expr, x.args)
+ {
+ if (!(*this)(expr))
+ return false;
+ }
+
+ current->op(
+ op_call,
+ p->nargs(),
+ p->get_address());
+ current->link_to(x.function_name.name, p->get_address());
+
+ return true;
+ }
+
+ namespace
+ {
+ int precedence[] = {
+ // precedence 1
+ 1, // op_comma
+
+ // precedence 2
+ 2, // op_assign
+ 2, // op_plus_assign
+ 2, // op_minus_assign
+ 2, // op_times_assign
+ 2, // op_divide_assign
+ 2, // op_mod_assign
+ 2, // op_bit_and_assign
+ 2, // op_bit_xor_assign
+ 2, // op_bitor_assign
+ 2, // op_shift_left_assign
+ 2, // op_shift_right_assign
+
+ // precedence 3
+ 3, // op_logical_or
+
+ // precedence 4
+ 4, // op_logical_and
+
+ // precedence 5
+ 5, // op_bit_or
+
+ // precedence 6
+ 6, // op_bit_xor
+
+ // precedence 7
+ 7, // op_bit_and
+
+ // precedence 8
+ 8, // op_equal
+ 8, // op_not_equal
+
+ // precedence 9
+ 9, // op_less
+ 9, // op_less_equal
+ 9, // op_greater
+ 9, // op_greater_equal
+
+ // precedence 10
+ 10, // op_shift_left
+ 10, // op_shift_right
+
+ // precedence 11
+ 11, // op_plus
+ 11, // op_minus
+
+ // precedence 12
+ 12, // op_times
+ 12, // op_divide
+ 12 // op_mod
+ };
+ }
+
+ inline int precedence_of(token_ids::type op)
+ {
+ return precedence[op & 0xFF];
+ }
+
+ // The Shunting-yard algorithm
+ bool compiler::compile_expression(
+ int min_precedence,
+ std::list<ast::operation>::const_iterator& rbegin,
+ std::list<ast::operation>::const_iterator rend)
+ {
+ while ((rbegin != rend) && (precedence_of(rbegin->operator_) >= min_precedence))
+ {
+ token_ids::type op = rbegin->operator_;
+ if (!boost::apply_visitor(*this, rbegin->operand_))
+ return false;
+ ++rbegin;
+
+ while ((rbegin != rend) && (precedence_of(rbegin->operator_) > precedence_of(op)))
+ {
+ token_ids::type next_op = rbegin->operator_;
+ compile_expression(precedence_of(next_op), rbegin, rend);
+ }
+ (*this)(op);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ std::list<ast::operation>::const_iterator rbegin = x.rest.begin();
+ if (!compile_expression(0, rbegin, x.rest.end()))
+ return false;
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = current->find_var(x.lhs.name);
+ if (p == 0)
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ current->op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.lhs.name);
+ if (p != 0)
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+ if (x.rhs) // if there's an RHS initializer
+ {
+ bool r = (*this)(*x.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ current->add_var(x.lhs.name);
+ current->op(op_store, *current->find_var(x.lhs.name));
+ }
+ return r;
+ }
+ else
+ {
+ current->add_var(x.lhs.name);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = current->size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ (*current)[skip] = current->size()-skip; // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an alse
+ {
+ (*current)[skip] += 2; // adjust for the "else" jump
+ current->op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ (*current)[exit] = current->size()-exit;// now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ std::size_t loop = current->size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ current->op(op_jump,
+ int(loop-1) - int(current->size())); // loop back
+ (*current)[exit] = current->size()-exit; // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(x.id, current_function_name + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ if (!(*this)(*x.expr))
+ return false;
+ }
+ current->op(op_return);
+ return true;
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ if (functions.find(x.function_name.name) != functions.end())
+ {
+ error_handler(x.function_name.id, "Duplicate function: " + x.function_name.name);
+ return false;
+ }
+ boost::shared_ptr<code_gen::function>& p = functions[x.function_name.name];
+ p.reset(new code_gen::function(code, x.args.size()));
+ current = p.get();
+ current_function_name = x.function_name.name;
+
+ // op_stk_adj 0 for now. we'll know how many variables
+ // we'll have later and add them
+ current->op(op_stk_adj, 0);
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ current->add_var(arg.name);
+ }
+
+ if (!(*this)(x.body))
+ return false;
+ (*current)[1] = current->nvars(); // now store the actual number of variables
+ // this includes the arguments
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ // Jump to the main function
+ code.push_back(op_jump);
+ code.push_back(0); // we will fill this in later when we finish compiling
+ // and we know where the main function is
+
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ if (!(*this)(f))
+ {
+ code.clear();
+ return false;
+ }
+ }
+ // find the main function
+ boost::shared_ptr<code_gen::function> p =
+ find_function("main");
+
+ if (!p) // main function not found
+ {
+ std::cerr << "Error: main function not defined" << std::endl;
+ return false;
+ }
+ code[1] = p->get_address()-1; // jump to this (main function) address
+
+ return true;
+ }
+
+ void compiler::print_assembler() const
+ {
+ typedef std::pair<std::string, boost::shared_ptr<code_gen::function> > pair;
+ BOOST_FOREACH(pair const& p, functions)
+ {
+ std::cout << ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" << std::endl;
+ std::cout << p.second->get_address() << ": function " << p.first << std::endl;
+ p.second->print_assembler();
+ }
+ }
+
+ boost::shared_ptr<code_gen::function>
+ compiler::find_function(std::string const& name) const
+ {
+ function_table::const_iterator i = functions.find(name);
+ if (i == functions.end())
+ return boost::shared_ptr<code_gen::function>();
+ else
+ return i->second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.hpp
new file mode 100644
index 00000000..b49c0ac4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.hpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP)
+#define BOOST_SPIRIT_CONJURE_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Function
+ ///////////////////////////////////////////////////////////////////////////
+ struct function
+ {
+ function(std::vector<int>& code, int nargs)
+ : code(code), address(code.size()), size_(0), nargs_(nargs) {}
+
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[address+i]; }
+ int const& operator[](std::size_t i) const { return code[address+i]; }
+ std::size_t size() const { return size_; }
+ std::size_t get_address() const { return address; }
+
+ int nargs() const { return nargs_; }
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+ void link_to(std::string const& name, std::size_t address);
+
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::map<std::size_t, std::string> function_calls;
+ std::vector<int>& code;
+ std::size_t address;
+ std::size_t size_;
+ std::size_t nargs_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(ErrorHandler& error_handler_)
+ : current(0)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x);
+ bool operator()(bool x);
+ bool operator()(ast::identifier const& x);
+ bool operator()(token_ids::type const& x);
+ bool operator()(ast::unary const& x);
+ bool operator()(ast::function_call const& x);
+ bool operator()(ast::expression const& x);
+ bool operator()(ast::assignment const& x);
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ void print_assembler() const;
+
+ boost::shared_ptr<code_gen::function>
+ find_function(std::string const& name) const;
+
+ std::vector<int>& get_code() { return code; }
+ std::vector<int> const& get_code() const { return code; }
+
+ private:
+
+ bool compile_expression(
+ int min_precedence,
+ std::list<ast::operation>::const_iterator& rbegin,
+ std::list<ast::operation>::const_iterator rend);
+
+ typedef std::map<std::string, boost::shared_ptr<code_gen::function> > function_table;
+
+ std::vector<int> code;
+ code_gen::function* current;
+ std::string current_function_name;
+ function_table functions;
+ bool void_return;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/config.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/config.hpp
new file mode 100644
index 00000000..70af0db0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/config.hpp
@@ -0,0 +1,51 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// The conjure lexer example can be built in 3 different variations:
+//
+// - With a lexer using runtime generated DFA tables
+// - With a lexer using pre-generated (static) DFA tables
+// - With a lexer using a pre-generated custom switch based state machine
+//
+// Use one of the following preprocessor constants to define, which of those
+// will be built:
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_DYNAMIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on pre-generated static DFA tables
+// #define CONJURE_LEXER_STATIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_STATIC_SWITCH 1
+
+///////////////////////////////////////////////////////////////////////////////
+// The default is to use the dynamic table driven lexer
+#if CONJURE_LEXER_DYNAMIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_SWITCH == 0
+
+#define CONJURE_LEXER_DYNAMIC_TABLES 1
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Make sure we have only one lexer type selected
+#if (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_TABLES != 0) || \
+ (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0) || \
+ (CONJURE_LEXER_STATIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0)
+
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer.hpp
new file mode 100644
index 00000000..d626840b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer.hpp
@@ -0,0 +1,483 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUL_25_2011_07_03_08)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUL_25_2011_07_03_08
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ enum {end_state_index, id_index, unique_id_index, state_index, bol_index,
+ eol_index, dead_state_index, dfa_offset};
+
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+ static std::size_t const lookup_[256] = {
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 7, 7, 41, 41, 7, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 7, 8, 41, 41, 41, 41, 9, 41,
+ 10, 11, 12, 13, 14, 15, 41, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 41, 19, 20, 21, 22, 41,
+ 41, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 41, 41, 41, 41, 18,
+ 41, 23, 18, 18, 24, 25, 26, 18,
+ 27, 28, 18, 18, 29, 18, 30, 31,
+ 18, 18, 32, 33, 34, 35, 36, 37,
+ 18, 18, 18, 38, 39, 40, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41 };
+ static std::size_t const dfa_alphabet_ = 42;
+ static std::size_t const dfa_[2604] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 27, 13, 11, 20, 21, 18, 16,
+ 24, 17, 19, 2, 26, 25, 14, 12,
+ 15, 26, 26, 7, 4, 26, 6, 26,
+ 26, 26, 9, 26, 3, 26, 5, 8,
+ 22, 10, 23, 0, 1, 35, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 28, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 29,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 30, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 32, 26,
+ 26, 26, 31, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 33, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 34, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 35, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 36, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 61, 26, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 262177, 20, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 39,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131091, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 40, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131093,
+ 14, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 41, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 393241, 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 393242, 17, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131099, 18, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131100,
+ 19, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 42, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 40, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 41, 22, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 123, 23, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 125,
+ 24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 44, 25, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 59, 27, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 34,
+ 30, 0, 0, 0, 0, 27, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 43, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 44,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 45, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 46, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65538, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 47, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 48, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 49, 26, 26, 26, 0, 0, 0, 0,
+ 1, 131084, 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 131085, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131089, 10, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131090,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 131092, 13, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 131094, 15, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 42, 42, 42, 42, 42,
+ 50, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 51,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 43, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 52, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65537, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 53,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 54, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 55, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 56, 56, 56, 56, 56,
+ 50, 56, 56, 56, 57, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 1, 36,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65536, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65539, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 58, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 59, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 33, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 65540, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 61, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 57, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 65541, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0 };
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
+ Iterator curr_ = start_token_;
+ bool end_state_ = *ptr_ != 0;
+ std::size_t id_ = *(ptr_ + id_index);
+ std::size_t uid_ = *(ptr_ + unique_id_index);
+ Iterator end_token_ = start_token_;
+
+ while (curr_ != end_)
+ {
+ std::size_t const state_ =
+ ptr_[lookup_[static_cast<unsigned char>(*curr_++)]];
+
+ if (state_ == 0) break;
+
+ ptr_ = &dfa_[state_ * dfa_alphabet_];
+
+ if (*ptr_)
+ {
+ end_state_ = true;
+ id_ = *(ptr_ + id_index);
+ uid_ = *(ptr_ + unique_id_index);
+ end_token_ = curr_;
+ }
+ }
+
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer_generate.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer_generate.cpp
new file mode 100644
index 00000000..1ba8fac0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer_generate.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This small utility program generates the 2 static lexers, the static table
+// driven and the static switch based lexer.
+
+#include <fstream>
+#include <iostream>
+
+#include "lexer_def.hpp"
+#include <boost/spirit/include/lex_generate_static_lexertl.hpp>
+
+int main()
+{
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+
+ lexer_type lexer;
+
+ // first generate the static switch based lexer
+ std::ofstream out_static("conjure_static_switch_lexer.hpp");
+
+ bool result = boost::spirit::lex::lexertl::generate_static_switch(
+ lexer, out_static, "conjure_static_switch");
+ if (!result) {
+ std::cerr << "Failed to generate static switch based lexer\n";
+ return -1;
+ }
+
+ // now generate the static table based lexer
+ std::ofstream out("conjure_static_lexer.hpp");
+ result = boost::spirit::lex::lexertl::generate_static(
+ lexer, out, "conjure_static");
+ if (!result) {
+ std::cerr << "Failed to generate static table based lexer\n";
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_switch_lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_switch_lexer.hpp
new file mode 100644
index 00000000..3b23016b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_switch_lexer.hpp
@@ -0,0 +1,873 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUL_25_2011_07_03_08)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUL_25_2011_07_03_08
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static_switch[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static_switch = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static_switch (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ Iterator curr_ = start_token_;
+ bool end_state_ = false;
+ std::size_t id_ = npos;
+ std::size_t uid_ = npos;
+ Iterator end_token_ = start_token_;
+
+ char ch_ = 0;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+
+ if (ch_ == 't') goto state0_2;
+
+ if (ch_ == 'f') goto state0_3;
+
+ if (ch_ == 'v') goto state0_4;
+
+ if (ch_ == 'i') goto state0_5;
+
+ if (ch_ == 'e') goto state0_6;
+
+ if (ch_ == 'w') goto state0_7;
+
+ if (ch_ == 'r') goto state0_8;
+
+ if (ch_ == '|') goto state0_9;
+
+ if (ch_ == '&') goto state0_10;
+
+ if (ch_ == '=') goto state0_11;
+
+ if (ch_ == '!') goto state0_12;
+
+ if (ch_ == '<') goto state0_13;
+
+ if (ch_ == '>') goto state0_14;
+
+ if (ch_ == '+') goto state0_15;
+
+ if (ch_ == '-') goto state0_16;
+
+ if (ch_ == '*') goto state0_17;
+
+ if (ch_ == '/') goto state0_18;
+
+ if (ch_ == '(') goto state0_19;
+
+ if (ch_ == ')') goto state0_20;
+
+ if (ch_ == '{') goto state0_21;
+
+ if (ch_ == '}') goto state0_22;
+
+ if (ch_ == ',') goto state0_23;
+
+ if (ch_ == ';') goto state0_24;
+
+ if ((ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'g' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'q') || ch_ == 's' || ch_ == 'u' || (ch_ >= 'x' && ch_ <= 'z')) goto state0_25;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_1:
+ end_state_ = true;
+ id_ = 35;
+ uid_ = 0;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+ goto end;
+
+state0_2:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_27;
+ goto end;
+
+state0_3:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'b' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'a') goto state0_28;
+ goto end;
+
+state0_4:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'n') || (ch_ >= 'p' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'o') goto state0_29;
+ goto end;
+
+state0_5:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'e') || (ch_ >= 'g' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_30;
+
+ if (ch_ == 'f') goto state0_31;
+ goto end;
+
+state0_6:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_32;
+ goto end;
+
+state0_7:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'g') || (ch_ >= 'i' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'h') goto state0_33;
+ goto end;
+
+state0_8:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_34;
+ goto end;
+
+state0_9:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '|') goto state0_35;
+ goto end;
+
+state0_10:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '&') goto state0_36;
+ goto end;
+
+state0_11:
+ end_state_ = true;
+ id_ = 61;
+ uid_ = 26;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_37;
+ goto end;
+
+state0_12:
+ end_state_ = true;
+ id_ = 262177;
+ uid_ = 20;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_38;
+ goto end;
+
+state0_13:
+ end_state_ = true;
+ id_ = 131091;
+ uid_ = 12;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_39;
+ goto end;
+
+state0_14:
+ end_state_ = true;
+ id_ = 131093;
+ uid_ = 14;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_40;
+ goto end;
+
+state0_15:
+ end_state_ = true;
+ id_ = 393241;
+ uid_ = 16;
+ end_token_ = curr_;
+ goto end;
+
+state0_16:
+ end_state_ = true;
+ id_ = 393242;
+ uid_ = 17;
+ end_token_ = curr_;
+ goto end;
+
+state0_17:
+ end_state_ = true;
+ id_ = 131099;
+ uid_ = 18;
+ end_token_ = curr_;
+ goto end;
+
+state0_18:
+ end_state_ = true;
+ id_ = 131100;
+ uid_ = 19;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_41;
+ goto end;
+
+state0_19:
+ end_state_ = true;
+ id_ = 40;
+ uid_ = 21;
+ end_token_ = curr_;
+ goto end;
+
+state0_20:
+ end_state_ = true;
+ id_ = 41;
+ uid_ = 22;
+ end_token_ = curr_;
+ goto end;
+
+state0_21:
+ end_state_ = true;
+ id_ = 123;
+ uid_ = 23;
+ end_token_ = curr_;
+ goto end;
+
+state0_22:
+ end_state_ = true;
+ id_ = 125;
+ uid_ = 24;
+ end_token_ = curr_;
+ goto end;
+
+state0_23:
+ end_state_ = true;
+ id_ = 44;
+ uid_ = 25;
+ end_token_ = curr_;
+ goto end;
+
+state0_24:
+ end_state_ = true;
+ id_ = 59;
+ uid_ = 27;
+ end_token_ = curr_;
+ goto end;
+
+state0_25:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_26:
+ end_state_ = true;
+ id_ = 34;
+ uid_ = 30;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_27:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_42;
+ goto end;
+
+state0_28:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_43;
+ goto end;
+
+state0_29:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_44;
+ goto end;
+
+state0_30:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_45;
+ goto end;
+
+state0_31:
+ end_state_ = true;
+ id_ = 65538;
+ uid_ = 4;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_32:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_46;
+ goto end;
+
+state0_33:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_47;
+ goto end;
+
+state0_34:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_48;
+ goto end;
+
+state0_35:
+ end_state_ = true;
+ id_ = 131084;
+ uid_ = 8;
+ end_token_ = curr_;
+ goto end;
+
+state0_36:
+ end_state_ = true;
+ id_ = 131085;
+ uid_ = 9;
+ end_token_ = curr_;
+ goto end;
+
+state0_37:
+ end_state_ = true;
+ id_ = 131089;
+ uid_ = 10;
+ end_token_ = curr_;
+ goto end;
+
+state0_38:
+ end_state_ = true;
+ id_ = 131090;
+ uid_ = 11;
+ end_token_ = curr_;
+ goto end;
+
+state0_39:
+ end_state_ = true;
+ id_ = 131092;
+ uid_ = 13;
+ end_token_ = curr_;
+ goto end;
+
+state0_40:
+ end_state_ = true;
+ id_ = 131094;
+ uid_ = 15;
+ end_token_ = curr_;
+ goto end;
+
+state0_41:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_41;
+
+ if (ch_ == '*') goto state0_49;
+ goto end;
+
+state0_42:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_50;
+ goto end;
+
+state0_43:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_42;
+ goto end;
+
+state0_44:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'c') || (ch_ >= 'e' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'd') goto state0_51;
+ goto end;
+
+state0_45:
+ end_state_ = true;
+ id_ = 65537;
+ uid_ = 3;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_46:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_52;
+ goto end;
+
+state0_47:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_53;
+ goto end;
+
+state0_48:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_54;
+ goto end;
+
+state0_49:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_49;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+ goto end;
+
+state0_50:
+ end_state_ = true;
+ id_ = 36;
+ uid_ = 1;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_51:
+ end_state_ = true;
+ id_ = 65536;
+ uid_ = 2;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_52:
+ end_state_ = true;
+ id_ = 65539;
+ uid_ = 5;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_53:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_57;
+ goto end;
+
+state0_54:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_58;
+ goto end;
+
+state0_55:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_55;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_56:
+ end_state_ = true;
+ id_ = 33;
+ uid_ = 29;
+ end_token_ = curr_;
+ goto end;
+
+state0_57:
+ end_state_ = true;
+ id_ = 65540;
+ uid_ = 6;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_58:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_60;
+ goto end;
+
+state0_59:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_60:
+ end_state_ = true;
+ id_ = 65541;
+ uid_ = 7;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+
+end:
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static_switch
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static_switch;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static_switch[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static_switch(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/error_handler.hpp
new file mode 100644
index 00000000..2b1ee5b2
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/error_handler.hpp
@@ -0,0 +1,105 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator, typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(BaseIterator first, BaseIterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ // retrieve underlying iterator from current token, err_pos points
+ // to the last validly matched token, so we use its end iterator
+ // as the error position
+ BaseIterator err_pos_base = err_pos->matched().end();
+ std::cout << message << what << std::endl;
+ if (err_pos_base != BaseIterator())
+ dump_error_line(err_pos_base);
+ }
+
+ void dump_error_line(BaseIterator err_pos_base) const
+ {
+ int line;
+ BaseIterator line_start = get_pos(err_pos_base, line);
+ if (err_pos_base != last)
+ {
+ std::cout << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos_base; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file.\n";
+ }
+
+ }
+
+ BaseIterator get_pos(BaseIterator err_pos, int& line) const
+ {
+ line = 1;
+ BaseIterator i = first;
+ BaseIterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(BaseIterator err_pos) const
+ {
+ BaseIterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ BaseIterator first;
+ BaseIterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.cpp
new file mode 100644
index 00000000..5b51ce36
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::expression<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.hpp
new file mode 100644
index 00000000..a5d431ef
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.hpp
@@ -0,0 +1,58 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CONJURE_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct expression : qi::grammar<Iterator, ast::expression()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ expression(error_handler_type& error_handler, Lexer const& l);
+
+ Lexer const& lexer;
+
+ qi::rule<Iterator, ast::expression()> expr;
+ qi::rule<Iterator, ast::operand()> unary_expr, primary_expr;
+ qi::rule<Iterator, ast::function_call()> function_call;
+ qi::rule<Iterator, std::list<ast::expression>()> argument_list;
+ qi::rule<Iterator, std::string()> identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression_def.hpp
new file mode 100644
index 00000000..795051eb
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression_def.hpp
@@ -0,0 +1,94 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/lex_plain_token.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ expression<Iterator, Lexer>::expression(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : expression::base_type(expr), lexer(l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::tokenid_mask_type tokenid_mask;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ unary_expr
+ >> *(tokenid_mask(token_ids::op_binary) > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (tokenid_mask(token_ids::op_unary) > unary_expr)
+ ;
+
+ primary_expr =
+ lexer.lit_uint
+ | function_call
+ | identifier
+ | lexer.true_or_false
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier = lexer.identifier;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (unary_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.cpp
new file mode 100644
index 00000000..98c8169b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "function_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::function<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.hpp
new file mode 100644
index 00000000..fc5263f1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.hpp
@@ -0,0 +1,36 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_FUNCTION_HPP)
+#define BOOST_SPIRIT_CONJURE_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct function : qi::grammar<Iterator, ast::function()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ function(error_handler_type& error_handler, Lexer const& l);
+
+ statement<Iterator, Lexer> body;
+
+ qi::rule<Iterator, ast::identifier()> identifier;
+ qi::rule<Iterator, std::list<ast::identifier>()> argument_list;
+ qi::rule<Iterator, ast::function()> start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function_def.hpp
new file mode 100644
index 00000000..72bab856
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function_def.hpp
@@ -0,0 +1,64 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ function<Iterator, Lexer>::function(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : function::base_type(start), body(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ identifier = body.expr.identifier;
+ argument_list = -(identifier % ',');
+
+ start = (l.token("void") | l.token("int"))
+ > identifier
+ > '(' > argument_list > ')'
+ > '{' > body > '}'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ids.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ids.hpp
new file mode 100644
index 00000000..9446074c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ids.hpp
@@ -0,0 +1,154 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_IDS_HPP)
+#define BOOST_SPIRIT_CONJURE_IDS_HPP
+
+namespace client
+{
+ struct op_type
+ {
+ enum type
+ {
+ binary = 0x20000,
+ unary = 0x40000,
+ assign = 0x80000
+ };
+ };
+
+ struct op
+ {
+ enum type
+ {
+ // binary
+ comma,
+ assign,
+ plus_assign,
+ minus_assign,
+ times_assign,
+ divide_assign,
+ mod_assign,
+ bit_and_assign,
+ bit_xor_assign,
+ bit_or_assign,
+ shift_left_assign,
+ shift_right_assign,
+ logical_or,
+ logical_and,
+ bit_or,
+ bit_xor,
+ bit_and,
+ equal,
+ not_equal,
+ less,
+ less_equal,
+ greater,
+ greater_equal,
+ shift_left,
+ shift_right,
+ plus,
+ minus,
+ times,
+ divide,
+ mod,
+
+ // unary
+ plus_plus,
+ minus_minus,
+ compl_,
+ not_,
+ };
+ };
+
+ template <int type, int op>
+ struct make_op
+ {
+ static int const value = type + op;
+ };
+
+ template <op::type op>
+ struct unary_op : make_op<op_type::unary, op> {};
+
+ template <op::type op>
+ struct binary_op
+ : make_op<op_type::binary, op> {};
+
+ template <op::type op>
+ struct assign_op
+ : make_op<op_type::assign, op> {};
+
+ template <op::type op>
+ struct binary_or_unary_op
+ : make_op<op_type::unary | op_type::binary, op> {};
+
+ struct token_ids
+ {
+ enum type
+ {
+ // pseudo tags
+ invalid = -1,
+ op_binary = op_type::binary,
+ op_unary = op_type::unary,
+ op_assign = op_type::assign,
+
+ // binary / unary operators with common tokens
+ // '+' and '-' can be binary or unary
+ // (the lexer cannot distinguish which)
+ plus = binary_or_unary_op<op::plus>::value,
+ minus = binary_or_unary_op<op::minus>::value,
+
+ // binary operators
+ comma = binary_op<op::comma>::value,
+ assign = assign_op<op::assign>::value,
+ plus_assign = assign_op<op::plus_assign>::value,
+ minus_assign = assign_op<op::minus_assign>::value,
+ times_assign = assign_op<op::times_assign>::value,
+ divide_assign = assign_op<op::divide_assign>::value,
+ mod_assign = assign_op<op::mod_assign>::value,
+ bit_and_assign = assign_op<op::bit_and_assign>::value,
+ bit_xor_assign = assign_op<op::bit_xor_assign>::value,
+ bit_or_assign = assign_op<op::bit_or_assign>::value,
+ shift_left_assign = assign_op<op::shift_left_assign>::value,
+ shift_right_assign = assign_op<op::shift_right_assign>::value,
+ logical_or = binary_op<op::logical_or>::value,
+ logical_and = binary_op<op::logical_and>::value,
+ bit_or = binary_op<op::bit_or>::value,
+ bit_xor = binary_op<op::bit_xor>::value,
+ bit_and = binary_op<op::bit_and>::value,
+ equal = binary_op<op::equal>::value,
+ not_equal = binary_op<op::not_equal>::value,
+ less = binary_op<op::less>::value,
+ less_equal = binary_op<op::less_equal>::value,
+ greater = binary_op<op::greater>::value,
+ greater_equal = binary_op<op::greater_equal>::value,
+ shift_left = binary_op<op::shift_left>::value,
+ shift_right = binary_op<op::shift_right>::value,
+ times = binary_op<op::times>::value,
+ divide = binary_op<op::divide>::value,
+ mod = binary_op<op::mod>::value,
+
+ // unary operators with overlaps
+ // '++' and '--' can be prefix or postfix
+ // (the lexer cannot distinguish which)
+ plus_plus = unary_op<op::plus_plus>::value,
+ minus_minus = unary_op<op::minus_minus>::value,
+
+ // unary operators
+ compl_ = unary_op<op::compl_>::value,
+ not_ = unary_op<op::not_>::value,
+
+ // misc tags
+ identifier = op::not_ + 1,
+ comment,
+ whitespace,
+ lit_uint,
+ true_or_false
+ };
+ };
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.cpp
new file mode 100644
index 00000000..7ce7ec0c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.cpp
@@ -0,0 +1,17 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+template client::lexer::conjure_tokens<base_iterator_type>::conjure_tokens();
+template bool client::lexer::conjure_tokens<base_iterator_type>::add_keyword(
+ std::string const&);
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.hpp
new file mode 100644
index 00000000..c4945779
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.hpp
@@ -0,0 +1,128 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_HPP
+
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/lex_lexertl_position_token.hpp>
+
+#include "config.hpp"
+#include "ids.hpp"
+
+#if CONJURE_LEXER_STATIC_TABLES != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_lexer.hpp"
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_switch_lexer.hpp"
+#endif
+#include <boost/assert.hpp>
+
+namespace client { namespace lexer
+{
+ namespace lex = boost::spirit::lex;
+
+ ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ namespace lex = boost::spirit::lex;
+
+ template <typename BaseIterator>
+ struct get_lexer_type
+ {
+ // Our token needs to be able to carry several token values:
+ // std::string, unsigned int, and bool
+ typedef boost::mpl::vector<std::string, unsigned int, bool>
+ token_value_types;
+
+ // Using the position_token class as the token type to be returned
+ // from the lexer iterators allows to retain positional information
+ // as every token instance stores an iterator pair pointing to the
+ // matched input sequence.
+ typedef lex::lexertl::position_token<
+ BaseIterator, token_value_types, boost::mpl::false_
+ > token_type;
+
+#if CONJURE_LEXER_DYNAMIC_TABLES != 0
+ // use the lexer based on runtime generated DFA tables
+ typedef lex::lexertl::actor_lexer<token_type> type;
+#elif CONJURE_LEXER_STATIC_TABLES != 0
+ // use the lexer based on pre-generated static DFA tables
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static
+ > type;
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+ // use the lexer based on pre-generated static code
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static_switch
+ > type;
+#else
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator>
+ struct conjure_tokens
+ : lex::lexer<typename detail::get_lexer_type<BaseIterator>::type>
+ {
+ private:
+ // get the type of any qi::raw_token(...) and qi::token(...) constructs
+ typedef typename boost::spirit::result_of::terminal<
+ boost::spirit::tag::raw_token(token_ids::type)
+ >::type raw_token_spec;
+
+ typedef typename boost::spirit::result_of::terminal<
+ boost::spirit::tag::token(token_ids::type)
+ >::type token_spec;
+
+ typedef std::map<std::string, token_ids::type> keyword_map_type;
+
+ protected:
+ // add a keyword to the mapping table
+ bool add_keyword(std::string const& keyword);
+
+ public:
+ typedef BaseIterator base_iterator_type;
+
+ conjure_tokens();
+
+ // extract a raw_token(id) for the given registered keyword
+ raw_token_spec operator()(std::string const& kwd) const
+ {
+ namespace qi = boost::spirit::qi;
+ qi::raw_token_type raw_token;
+
+ typename keyword_map_type::const_iterator it = keywords_.find(kwd);
+ BOOST_ASSERT(it != keywords_.end());
+ return raw_token((it != keywords_.end()) ? (*it).second : token_ids::invalid);
+ }
+
+ // extract a token(id) for the given registered keyword
+ token_spec token(std::string const& kwd) const
+ {
+ namespace qi = boost::spirit::qi;
+ qi::token_type token;
+
+ typename keyword_map_type::const_iterator it = keywords_.find(kwd);
+ BOOST_ASSERT(it != keywords_.end());
+ return token((it != keywords_.end()) ? (*it).second : token_ids::invalid);
+ }
+
+ lex::token_def<std::string> identifier;
+ lex::token_def<unsigned int> lit_uint;
+ lex::token_def<bool> true_or_false;
+ keyword_map_type keywords_;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer_def.hpp
new file mode 100644
index 00000000..cab990f7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer_def.hpp
@@ -0,0 +1,74 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "lexer.hpp"
+
+namespace client { namespace lexer
+{
+ template <typename BaseIterator>
+ conjure_tokens<BaseIterator>::conjure_tokens()
+ : identifier("[a-zA-Z_][a-zA-Z_0-9]*", token_ids::identifier)
+ , lit_uint("[0-9]+", token_ids::lit_uint)
+ , true_or_false("true|false", token_ids::true_or_false)
+ {
+ lex::_pass_type _pass;
+
+ this->self = lit_uint | true_or_false;
+
+ add_keyword("void");
+ add_keyword("int");
+ add_keyword("if");
+ add_keyword("else");
+ add_keyword("while");
+ add_keyword("return");
+
+ this->self.add
+ ("\\|\\|", token_ids::logical_or)
+ ("&&", token_ids::logical_and)
+ ("==", token_ids::equal)
+ ("!=", token_ids::not_equal)
+ ("<", token_ids::less)
+ ("<=", token_ids::less_equal)
+ (">", token_ids::greater)
+ (">=", token_ids::greater_equal)
+ ("\\+", token_ids::plus)
+ ("\\-", token_ids::minus)
+ ("\\*", token_ids::times)
+ ("\\/", token_ids::divide)
+ ("!", token_ids::not_)
+ ;
+
+ this->self += lex::char_('(') | ')' | '{' | '}' | ',' | '=' | ';';
+
+ this->self +=
+ identifier
+ | lex::string("\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/", token_ids::comment)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ | lex::string("[ \t\n\r]+", token_ids::whitespace)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ ;
+ }
+
+ template <typename BaseIterator>
+ bool conjure_tokens<BaseIterator>::add_keyword(std::string const& keyword)
+ {
+ // add the token to the lexer
+ token_ids::type id = token_ids::type(this->get_next_id());
+ this->self.add(keyword, id);
+
+ // store the mapping for later retrieval
+ std::pair<typename keyword_map_type::iterator, bool> p =
+ keywords_.insert(typename keyword_map_type::value_type(keyword, id));
+
+ return p.second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/main.cpp
new file mode 100644
index 00000000..3e4e83c9
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/main.cpp
@@ -0,0 +1,131 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ HK June 3, 2011 ] Adding lexer
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "config.hpp"
+#include "function.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include "lexer.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+ typedef lexer_type::iterator_type iterator_type;
+
+ lexer_type lexer; // Our lexer
+
+ base_iterator_type first = source_code.begin();
+ base_iterator_type last = source_code.end();
+
+ iterator_type iter = lexer.begin(first, last);
+ iterator_type end = lexer.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<base_iterator_type, iterator_type>
+ error_handler(first, last); // Our error handler
+ client::parser::function<iterator_type, lexer_type>
+ function(error_handler, lexer); // Our parser
+ client::code_gen::compiler
+ compiler(error_handler); // Our compiler
+
+ // note: we don't need a skipper
+ bool success = parse(iter, end, +function, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ boost::shared_ptr<client::code_gen::function>
+ p = compiler.find_function("main");
+ if (!p)
+ return 1;
+
+ int nargs = argc-2;
+ if (p->nargs() != nargs)
+ {
+ std::cerr << "Error: main function requires " << p->nargs() << " arguments." << std::endl;
+ std::cerr << nargs << " supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ compiler.print_assembler();
+
+ // Push the arguments into our stack
+ for (int i = 0; i < nargs; ++i)
+ vm.get_stack()[i] = boost::lexical_cast<int>(argv[i+2]);
+
+ // Call the interpreter
+ int r = vm.execute(compiler.get_code());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ error_handler.dump_error_line(first);
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.cpp
new file mode 100644
index 00000000..ca85a61c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::statement<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.hpp
new file mode 100644
index 00000000..208ca247
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.hpp
@@ -0,0 +1,42 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_STATEMENT_HPP)
+#define BOOST_SPIRIT_CONJURE_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct statement : qi::grammar<Iterator, ast::statement_list()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ statement(error_handler_type& error_handler, Lexer const& l);
+
+ expression<Iterator, Lexer> expr;
+
+ qi::rule<Iterator, ast::statement_list()>
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement()> statement_;
+ qi::rule<Iterator, ast::variable_declaration()> variable_declaration;
+ qi::rule<Iterator, ast::assignment()> assignment;
+ qi::rule<Iterator, ast::if_statement()> if_statement;
+ qi::rule<Iterator, ast::while_statement()> while_statement;
+ qi::rule<Iterator, ast::return_statement()> return_statement;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement_def.hpp
new file mode 100644
index 00000000..ab937085
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement_def.hpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ statement<Iterator, Lexer>::statement(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : statement::base_type(statement_list), expr(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ ;
+
+ variable_declaration =
+ l("int")
+ > expr.identifier
+ > -('=' > expr)
+ > ';'
+ ;
+
+ assignment =
+ expr.identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ l("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ l("else")
+ > statement_
+ )
+ ;
+
+ while_statement =
+ l("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ l("return")
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (statement_)
+ (variable_declaration)
+ (assignment)
+ (if_statement)
+ (while_statement)
+ (compound_statement)
+ (return_statement)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in variable_declaration,
+ // assignment and return_statement, call annotation.
+ on_success(variable_declaration,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.cpp
new file mode 100644
index 00000000..af68f523
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.cpp
@@ -0,0 +1,160 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "config.hpp"
+#include "vm.hpp"
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (true)
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr += *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.hpp
new file mode 100644
index 00000000..0362eaf8
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.hpp
@@ -0,0 +1,82 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_VM_HPP)
+#define BOOST_SPIRIT_CONJURE_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ }
+
+ std::vector<int> const& get_stack() const { return stack; };
+ std::vector<int>& get_stack() { return stack; };
+
+ private:
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp
new file mode 100644
index 00000000..3b876431
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp
@@ -0,0 +1,141 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CONJURE_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ struct set_annotation_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_annotation_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ template <typename T>
+ void dispatch(T& x, boost::mpl::true_) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void dispatch(T& x, boost::mpl::false_) const
+ {
+ // no-op
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ typename boost::is_base_of<ast::tagged, T> is_tagged;
+ dispatch(x, is_tagged);
+ }
+ };
+
+ struct get_annotation_id
+ {
+ typedef int result_type;
+
+ int operator()(ast::function_call& x) const
+ {
+ return x.function_name.id;
+ }
+
+ template <typename T>
+ int dispatch(T& x, boost::mpl::true_) const
+ {
+ return x.id;
+ }
+
+ template <typename T>
+ int dispatch(T& x, boost::mpl::false_) const
+ {
+ return -1;
+ }
+
+ template <typename T>
+ int operator()(T& x) const
+ {
+ typename boost::is_base_of<ast::tagged, T> is_tagged;
+ return dispatch(x, is_tagged);
+ }
+ };
+
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_annotation_id(id), ast);
+ ast.id = id;
+ }
+
+ void operator()(ast::primary_expr& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_annotation_id(id), ast);
+ ast.id = id;
+ }
+
+ void operator()(ast::variable_declaration& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp
new file mode 100644
index 00000000..a77cb0ed
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp
@@ -0,0 +1,240 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_AST_HPP)
+#define BOOST_SPIRIT_CONJURE_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/spirit/include/support_extended_variant.hpp>
+#include <boost/spirit/include/support_attributes.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+#include "ids.hpp"
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary_expr;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ struct primary_expr :
+ tagged,
+ boost::spirit::extended_variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<expression>
+ >
+ {
+ primary_expr() : base_type() {}
+ primary_expr(bool val) : base_type(val) {}
+ primary_expr(unsigned int val) : base_type(val) {}
+ primary_expr(identifier const& val) : base_type(val) {}
+ primary_expr(expression const& val) : base_type(val) {}
+ primary_expr(primary_expr const& rhs)
+ : base_type(rhs.get()) {}
+ };
+
+ struct operand :
+ tagged,
+ boost::spirit::extended_variant<
+ nil
+ , primary_expr
+ , boost::recursive_wrapper<unary_expr>
+ , boost::recursive_wrapper<function_call>
+ >
+ {
+ operand() : base_type() {}
+ operand(primary_expr const& val) : base_type(val) {}
+ operand(unary_expr const& val) : base_type(val) {}
+ operand(function_call const& val) : base_type(val) {}
+ operand(operand const& rhs)
+ : base_type(rhs.get()) {}
+ };
+
+ struct unary_expr : tagged
+ {
+ token_ids::type operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ token_ids::type operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ token_ids::type operator_;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ nil
+ , variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ , boost::recursive_wrapper<expression>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ boost::optional<statement_list> body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary_expr,
+ (client::token_ids::type, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::token_ids::type, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::token_ids::type, operator_)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (boost::optional<client::ast::statement_list>, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp
new file mode 100644
index 00000000..e36ad770
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp
@@ -0,0 +1,1141 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "config.hpp"
+#include "compiler.hpp"
+#include "annotation.hpp"
+#include "vm.hpp"
+
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/range/adaptor/transformed.hpp>
+#include <boost/assert.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ value::value()
+ : v(0),
+ is_lvalue_(false),
+ builder(0)
+ {}
+
+ value::value(
+ llvm::Value* v,
+ bool is_lvalue_,
+ llvm::IRBuilder<>* builder)
+ : v(v),
+ is_lvalue_(is_lvalue_),
+ builder(builder)
+ {}
+
+ value::value(value const& rhs)
+ : v(rhs.v),
+ is_lvalue_(rhs.is_lvalue_),
+ builder(rhs.builder)
+ {}
+
+ bool value::is_lvalue() const
+ {
+ return is_lvalue_;
+ }
+
+ bool value::is_valid() const
+ {
+ return v != 0;
+ }
+
+ value::operator bool() const
+ {
+ return v != 0;
+ }
+
+ void value::name(char const* id)
+ {
+ v->setName(id);
+ }
+
+ void value::name(std::string const& id)
+ {
+ v->setName(id);
+ }
+
+ value::operator llvm::Value*() const
+ {
+ if (is_lvalue_)
+ {
+ BOOST_ASSERT(builder != 0);
+ return builder->CreateLoad(v, v->getName());
+ }
+ return v;
+ }
+
+ value& value::operator=(value const& rhs)
+ {
+ v = rhs.v;
+ is_lvalue_ = rhs.is_lvalue_;
+ builder = rhs.builder;
+ return *this;
+ }
+
+ value& value::assign(value const& rhs)
+ {
+ BOOST_ASSERT(is_lvalue());
+ BOOST_ASSERT(builder != 0);
+ builder->CreateStore(rhs, v);
+ return *this;
+ }
+
+ value operator-(value a)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateNeg(a, "neg_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator!(value a)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateNot(a, "not_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator+(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateAdd(a, b, "add_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator-(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateSub(a, b, "sub_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator*(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateMul(a, b, "mul_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator/(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateSDiv(a, b, "div_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator%(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateSRem(a, b, "mod_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator&(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateAnd(a, b, "and_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator|(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateOr(a, b, "or_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator^(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateXor(a, b, "xor_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator<<(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateShl(a, b, "shl_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator>>(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateLShr(a, b, "shr_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator==(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpEQ(a, b, "eq_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator!=(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpNE(a, b, "ne_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator<(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpSLT(a, b, "slt_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator<=(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpSLE(a, b, "sle_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator>(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpSGT(a, b, "sgt_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator>=(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpSGE(a, b, "sge_tmp"),
+ false, a.builder
+ );
+ }
+
+ struct function::to_value
+ {
+ typedef value result_type;
+ llvm_compiler* c;
+
+ to_value(llvm_compiler* c = 0) : c(c) {}
+
+ value operator()(llvm::Value& v) const
+ {
+ return c->val(&v);
+ }
+ };
+
+ bool basic_block::has_terminator() const
+ {
+ return b->getTerminator() != 0;
+ }
+
+ bool basic_block::is_valid() const
+ {
+ return b != 0;
+ }
+
+ function::operator llvm::Function*() const
+ {
+ return f;
+ }
+
+ std::size_t function::arg_size() const
+ {
+ return f->arg_size();
+ }
+
+ void function::add(basic_block const& b)
+ {
+ f->getBasicBlockList().push_back(b);
+ }
+
+ void function::erase_from_parent()
+ {
+ f->eraseFromParent();
+ }
+
+ basic_block function::last_block()
+ {
+ return &f->getBasicBlockList().back();
+ }
+
+ bool function::empty() const
+ {
+ return f->empty();
+ }
+
+ std::string function::name() const
+ {
+ return f->getName();
+ }
+
+ function::arg_range function::args() const
+ {
+ BOOST_ASSERT(c != 0);
+ arg_val_iterator first(f->arg_begin(), to_value());
+ arg_val_iterator last(f->arg_end(), to_value());
+ return arg_range(first, last);
+ }
+
+ bool function::is_valid() const
+ {
+ return f != 0;
+ }
+
+ void function::verify() const
+ {
+ llvm::verifyFunction(*f);
+ }
+
+ value llvm_compiler::val(unsigned int x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(int x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(bool x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(1, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(llvm::Value* v)
+ {
+ return value(v, false, &llvm_builder);
+ }
+
+ namespace
+ {
+ // Create an alloca instruction in the entry block of
+ // the function. This is used for mutable variables etc.
+ llvm::AllocaInst*
+ make_entry_block_alloca(
+ llvm::Function* f,
+ char const* name,
+ llvm::LLVMContext& context)
+ {
+ llvm::IRBuilder<> builder(
+ &f->getEntryBlock(),
+ f->getEntryBlock().begin());
+
+ return builder.CreateAlloca(
+ llvm::Type::getIntNTy(context, int_size), 0, name);
+ }
+ }
+
+ value llvm_compiler::var(char const* name)
+ {
+ llvm::Function* f = llvm_builder.GetInsertBlock()->getParent();
+ llvm::IRBuilder<> builder(
+ &f->getEntryBlock(),
+ f->getEntryBlock().begin());
+
+ llvm::AllocaInst* alloca = builder.CreateAlloca(
+ llvm::Type::getIntNTy(context(), int_size), 0, name);
+
+ return value(alloca, true, &llvm_builder);
+ }
+
+ struct value::to_llvm_value
+ {
+ typedef llvm::Value* result_type;
+ llvm::Value* operator()(value const& x) const
+ {
+ return x;
+ }
+ };
+
+ template <typename C>
+ llvm::Value* llvm_compiler::call_impl(
+ function callee,
+ C const& args_)
+ {
+ // Sigh. LLVM requires CreateCall arguments to be random access.
+ // It would have been better if it can accept forward iterators.
+ // I guess it needs the arguments to be in contiguous memory.
+ // So, we have to put the args into a temporary std::vector.
+ std::vector<llvm::Value*> args(
+ args_.begin(), args_.end());
+
+ // Check the args for null values. We can't have null values.
+ // Return 0 if we find one to flag error.
+ BOOST_FOREACH(llvm::Value* arg, args)
+ {
+ if (arg == 0)
+ return 0;
+ }
+
+ return llvm_builder.CreateCall(
+ callee, args.begin(), args.end(), "call_tmp");
+ }
+
+ template <typename Container>
+ value llvm_compiler::call(
+ function callee,
+ Container const& args)
+ {
+ llvm::Value* call = call_impl(
+ callee,
+ args | boost::adaptors::transformed(value::to_llvm_value()));
+
+ if (call == 0)
+ return val();
+ return value(call, false, &llvm_builder);
+ }
+
+ function llvm_compiler::get_function(char const* name)
+ {
+ return function(vm.module()->getFunction(name), this);
+ }
+
+ function llvm_compiler::get_current_function()
+ {
+ // get the current function
+ return function(llvm_builder.GetInsertBlock()->getParent(), this);
+ }
+
+ function llvm_compiler::declare_function(
+ bool void_return
+ , std::string const& name
+ , std::size_t nargs)
+ {
+ llvm::Type const* int_type =
+ llvm::Type::getIntNTy(context(), int_size);
+ llvm::Type const* void_type = llvm::Type::getVoidTy(context());
+
+ std::vector<llvm::Type const*> ints(nargs, int_type);
+ llvm::Type const* return_type = void_return ? void_type : int_type;
+
+ llvm::FunctionType* function_type =
+ llvm::FunctionType::get(void_return ? void_type : int_type, ints, false);
+
+ return function(llvm::Function::Create(
+ function_type, llvm::Function::ExternalLinkage,
+ name, vm.module()), this);
+ }
+
+ basic_block llvm_compiler::make_basic_block(
+ char const* name
+ , function parent
+ , basic_block before)
+ {
+ return llvm::BasicBlock::Create(context(), name, parent, before);
+ }
+
+ value llvm_compiler::var(std::string const& name)
+ {
+ return var(name.c_str());
+ }
+
+ function llvm_compiler::get_function(std::string const& name)
+ {
+ return get_function(name.c_str());
+ }
+
+ basic_block llvm_compiler::get_insert_block()
+ {
+ return llvm_builder.GetInsertBlock();
+ }
+
+ void llvm_compiler::set_insert_point(basic_block b)
+ {
+ llvm_builder.SetInsertPoint(b);
+ }
+
+ void llvm_compiler::conditional_branch(
+ value cond, basic_block true_br, basic_block false_br)
+ {
+ llvm_builder.CreateCondBr(cond, true_br, false_br);
+ }
+
+ void llvm_compiler::branch(basic_block b)
+ {
+ llvm_builder.CreateBr(b);
+ }
+
+ void llvm_compiler::return_()
+ {
+ llvm_builder.CreateRetVoid();
+ }
+
+ void llvm_compiler::return_(value v)
+ {
+ llvm_builder.CreateRet(v);
+ }
+
+ void llvm_compiler::optimize_function(function f)
+ {
+ // Optimize the function.
+ fpm.run(*f);
+ }
+
+ void llvm_compiler::init_fpm()
+ {
+ // Set up the optimizer pipeline. Start with registering info about how the
+ // target lays out data structures.
+ fpm.add(new llvm::TargetData(*vm.execution_engine()->getTargetData()));
+ // Provide basic AliasAnalysis support for GVN.
+ fpm.add(llvm::createBasicAliasAnalysisPass());
+ // Promote allocas to registers.
+ fpm.add(llvm::createPromoteMemoryToRegisterPass());
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ fpm.add(llvm::createInstructionCombiningPass());
+ // Reassociate expressions.
+ fpm.add(llvm::createReassociatePass());
+ // Eliminate Common SubExpressions.
+ fpm.add(llvm::createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ fpm.add(llvm::createCFGSimplificationPass());
+
+ fpm.doInitialization();
+ }
+
+ value compiler::operator()(unsigned int x)
+ {
+ return val(x);
+ }
+
+ value compiler::operator()(bool x)
+ {
+ return val(x);
+ }
+
+ value compiler::operator()(ast::primary_expr const& x)
+ {
+ return boost::apply_visitor(*this, x.get());
+ }
+
+ value compiler::operator()(ast::identifier const& x)
+ {
+ // Look this variable up in the function.
+ if (locals.find(x.name) == locals.end())
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return val();
+ }
+ return locals[x.name];
+ }
+
+ value compiler::operator()(ast::unary_expr const& x)
+ {
+ value operand = boost::apply_visitor(*this, x.operand_);
+ if (!operand.is_valid())
+ return val();
+
+ switch (x.operator_)
+ {
+ case token_ids::compl_: return operand ^ val(-1);
+ case token_ids::minus: return -operand;
+ case token_ids::not_: return !operand;
+ case token_ids::plus: return operand;
+ case token_ids::plus_plus:
+ {
+ if (!operand.is_lvalue())
+ {
+ error_handler(x.id, "++ needs an var");
+ return val();
+ }
+
+ value r = operand + val(1);
+ operand.assign(r);
+ return operand;
+ }
+ case token_ids::minus_minus:
+ {
+ if (!operand.is_lvalue())
+ {
+ error_handler(x.id, "-- needs an var");
+ return val();
+ }
+
+ value r = operand - val(1);
+ operand.assign(r);
+ return operand;
+ }
+ default:
+ BOOST_ASSERT(0);
+ return val();
+ }
+ }
+
+ namespace
+ {
+ struct compile_args
+ {
+ compiler& c;
+ compile_args(compiler& c) : c(c) {}
+
+ typedef value result_type;
+ value operator()(ast::expression const& expr) const
+ {
+ return c(expr);
+ }
+ };
+ }
+
+ value compiler::operator()(ast::function_call const& x)
+ {
+ function callee = get_function(x.function_name.name);
+ if (!callee.is_valid())
+ {
+ error_handler(x.function_name.id,
+ "Function not found: " + x.function_name.name);
+ return val();
+ }
+
+ if (callee.arg_size() != x.args.size())
+ {
+ error_handler(x.function_name.id,
+ "Wrong number of arguments: " + x.function_name.name);
+ return val();
+ }
+
+ return call(callee,
+ x.args | boost::adaptors::transformed(compile_args(*this)));
+ }
+
+ namespace
+ {
+ int precedence[] = {
+ // precedence 1
+ 1, // op_comma
+
+ // precedence 2
+ 2, // op_assign
+ 2, // op_plus_assign
+ 2, // op_minus_assign
+ 2, // op_times_assign
+ 2, // op_divide_assign
+ 2, // op_mod_assign
+ 2, // op_bit_and_assign
+ 2, // op_bit_xor_assign
+ 2, // op_bitor_assign
+ 2, // op_shift_left_assign
+ 2, // op_shift_right_assign
+
+ // precedence 3
+ 3, // op_logical_or
+
+ // precedence 4
+ 4, // op_logical_and
+
+ // precedence 5
+ 5, // op_bit_or
+
+ // precedence 6
+ 6, // op_bit_xor
+
+ // precedence 7
+ 7, // op_bit_and
+
+ // precedence 8
+ 8, // op_equal
+ 8, // op_not_equal
+
+ // precedence 9
+ 9, // op_less
+ 9, // op_less_equal
+ 9, // op_greater
+ 9, // op_greater_equal
+
+ // precedence 10
+ 10, // op_shift_left
+ 10, // op_shift_right
+
+ // precedence 11
+ 11, // op_plus
+ 11, // op_minus
+
+ // precedence 12
+ 12, // op_times
+ 12, // op_divide
+ 12 // op_mod
+ };
+ }
+
+ inline int precedence_of(token_ids::type op)
+ {
+ return precedence[op & 0xFF];
+ }
+
+ value compiler::compile_binary_expression(
+ value lhs, value rhs, token_ids::type op)
+ {
+ switch (op)
+ {
+ case token_ids::plus: return lhs + rhs;
+ case token_ids::minus: return lhs - rhs;
+ case token_ids::times: return lhs * rhs;
+ case token_ids::divide: return lhs / rhs;
+ case token_ids::mod: return lhs % rhs;
+
+ case token_ids::logical_or:
+ case token_ids::bit_or: return lhs | rhs;
+
+ case token_ids::logical_and:
+ case token_ids::bit_and: return lhs & rhs;
+
+ case token_ids::bit_xor: return lhs ^ rhs;
+ case token_ids::shift_left: return lhs << rhs;
+ case token_ids::shift_right: return lhs >> rhs;
+
+ case token_ids::equal: return lhs == rhs;
+ case token_ids::not_equal: return lhs != rhs;
+ case token_ids::less: return lhs < rhs;
+ case token_ids::less_equal: return lhs <= rhs;
+ case token_ids::greater: return lhs > rhs;
+ case token_ids::greater_equal: return lhs >= rhs;
+
+ default: BOOST_ASSERT(0); return val();
+ }
+ }
+
+ // The Shunting-yard algorithm
+ value compiler::compile_expression(
+ int min_precedence,
+ value lhs,
+ std::list<ast::operation>::const_iterator& rest_begin,
+ std::list<ast::operation>::const_iterator rest_end)
+ {
+ while ((rest_begin != rest_end) &&
+ (precedence_of(rest_begin->operator_) >= min_precedence))
+ {
+ token_ids::type op = rest_begin->operator_;
+ value rhs = boost::apply_visitor(*this, rest_begin->operand_);
+ if (!rhs.is_valid())
+ return val();
+ ++rest_begin;
+
+ while ((rest_begin != rest_end) &&
+ (precedence_of(rest_begin->operator_) > precedence_of(op)))
+ {
+ token_ids::type next_op = rest_begin->operator_;
+ rhs = compile_expression(
+ precedence_of(next_op), rhs, rest_begin, rest_end);
+ }
+
+ lhs = compile_binary_expression(lhs, rhs, op);
+ }
+ return lhs;
+ }
+
+ value compiler::operator()(ast::expression const& x)
+ {
+ value lhs = boost::apply_visitor(*this, x.first);
+ if (!lhs.is_valid())
+ return val();
+ std::list<ast::operation>::const_iterator rest_begin = x.rest.begin();
+ return compile_expression(0, lhs, rest_begin, x.rest.end());
+ }
+
+ value compiler::operator()(ast::assignment const& x)
+ {
+ if (locals.find(x.lhs.name) == locals.end())
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return val();
+ }
+
+ value lhs = locals[x.lhs.name];
+ value rhs = (*this)(x.rhs);
+ if (!rhs.is_valid())
+ return val();
+
+ if (x.operator_ == token_ids::assign)
+ {
+ lhs.assign(rhs);
+ return lhs;
+ }
+
+ value result;
+ switch (x.operator_)
+ {
+ case token_ids::plus_assign: result = lhs + rhs; break;
+ case token_ids::minus_assign: result = lhs - rhs; break;
+ case token_ids::times_assign: result = lhs * rhs; break;
+ case token_ids::divide_assign: result = lhs / rhs; break;
+ case token_ids::mod_assign: result = lhs % rhs; break;
+ case token_ids::bit_and_assign: result = lhs & rhs; break;
+ case token_ids::bit_xor_assign: result = lhs ^ rhs; break;
+ case token_ids::bit_or_assign: result = lhs | rhs; break;
+ case token_ids::shift_left_assign: result = lhs << rhs; break;
+ case token_ids::shift_right_assign: result = lhs >> rhs; break;
+ default: BOOST_ASSERT(0); return val();
+ }
+
+ lhs.assign(result);
+ return lhs;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ if (locals.find(x.lhs.name) != locals.end())
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+
+ value init;
+ std::string const& name = x.lhs.name;
+
+ if (x.rhs) // if there's an RHS initializer
+ {
+ init = (*this)(*x.rhs);
+ if (!init.is_valid()) // don't add the variable if the RHS fails
+ return false;
+ }
+
+ value var_ = var(name.c_str());
+ if (init.is_valid())
+ var_.assign(init);
+
+ // Remember this binding.
+ locals[name] = var_;
+ return true;
+ }
+
+ struct compiler::statement_compiler : compiler
+ {
+ typedef bool result_type;
+ };
+
+ compiler::statement_compiler& compiler::as_statement()
+ {
+ return *static_cast<statement_compiler*>(this);
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ if (boost::get<ast::nil>(&x) != 0) // empty statement
+ return true;
+ return boost::apply_visitor(as_statement(), x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ value condition = (*this)(x.condition);
+ if (!condition.is_valid())
+ return false;
+
+ function f = get_current_function();
+
+ // Create blocks for the then and else cases. Insert the 'then' block at the
+ // end of the function.
+ basic_block then_block = make_basic_block("if.then", f);
+ basic_block else_block;
+ basic_block exit_block;
+
+ if (x.else_)
+ {
+ else_block = make_basic_block("if.else");
+ conditional_branch(condition, then_block, else_block);
+ }
+ else
+ {
+ exit_block = make_basic_block("if.end");
+ conditional_branch(condition, then_block, exit_block);
+ }
+
+ // Emit then value.
+ set_insert_point(then_block);
+ if (!(*this)(x.then))
+ return false;
+ if (!then_block.has_terminator())
+ {
+ if (!exit_block.is_valid())
+ exit_block = make_basic_block("if.end");
+ branch(exit_block);
+ }
+ // Codegen of 'then' can change the current block, update then_block
+ then_block = get_insert_block();
+
+ if (x.else_)
+ {
+ // Emit else block.
+ f.add(else_block);
+ set_insert_point(else_block);
+ if (!(*this)(*x.else_))
+ return false;
+ if (!else_block.has_terminator())
+ {
+ if (!exit_block.is_valid())
+ exit_block = make_basic_block("if.end");
+ branch(exit_block);
+ }
+ // Codegen of 'else' can change the current block, update else_block
+ else_block = get_insert_block();
+ }
+
+ if (exit_block.is_valid())
+ {
+ // Emit exit block
+ f.add(exit_block);
+ set_insert_point(exit_block);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ function f = get_current_function();
+
+ basic_block cond_block = make_basic_block("while.cond", f);
+ basic_block body_block = make_basic_block("while.body");
+ basic_block exit_block = make_basic_block("while.end");
+
+ branch(cond_block);
+ set_insert_point(cond_block);
+ value condition = (*this)(x.condition);
+ if (!condition.is_valid())
+ return false;
+ conditional_branch(condition, body_block, exit_block);
+ f.add(body_block);
+ set_insert_point(body_block);
+
+ if (!(*this)(x.body))
+ return false;
+
+ if (!body_block.has_terminator())
+ branch(cond_block); // loop back
+
+ // Emit exit block
+ f.add(exit_block);
+ set_insert_point(exit_block);
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(
+ x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(
+ x.id, current_function_name
+ + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ value return_val = (*this)(*x.expr);
+ if (!return_val.is_valid())
+ return false;
+ return_var.assign(return_val);
+ }
+
+ branch(return_block);
+ return true;
+ }
+
+ function compiler::function_decl(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ current_function_name = x.function_name.name;
+
+ function f =
+ declare_function(
+ void_return
+ , current_function_name
+ , x.args.size());
+
+ // If function conflicted, the function already exixts. If it has a
+ // body, don't allow redefinition or reextern.
+ if (f.name() != current_function_name)
+ {
+ // Delete the one we just made and get the existing one.
+ f.erase_from_parent();
+ f = get_function(current_function_name);
+
+ // If function already has a body, reject this.
+ if (!f.empty())
+ {
+ error_handler(
+ x.function_name.id,
+ "Duplicate function: " + x.function_name.name);
+ return function();
+ }
+
+ // If function took a different number of args, reject.
+ if (f.arg_size() != x.args.size())
+ {
+ error_handler(
+ x.function_name.id,
+ "Redefinition of function with different # args: "
+ + x.function_name.name);
+ return function();
+ }
+
+ // Set names for all arguments.
+ function::arg_range rng = f.args();
+ function::arg_range::const_iterator iter = rng.begin();
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ iter->name(arg.name);
+ ++iter;
+ }
+ }
+ return f;
+ }
+
+ void compiler::function_allocas(ast::function const& x, function f)
+ {
+ // Create variables for each argument and register the
+ // argument in the symbol table so that references to it will succeed.
+ function::arg_range rng = f.args();
+ function::arg_range::const_iterator iter = rng.begin();
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ // Create an arg_ for this variable.
+ value arg_ = var(arg.name);
+
+ // Store the initial value into the arg_.
+ arg_.assign(*iter);
+
+ // Add arguments to variable symbol table.
+ locals[arg.name] = arg_;
+ ++iter;
+ }
+
+ if (!void_return)
+ {
+ // Create an alloca for the return value
+ return_var = var("return.val");
+ }
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ ///////////////////////////////////////////////////////////////////////
+ // the signature:
+ function f = function_decl(x);
+ if (!f.is_valid())
+ return false;
+
+ ///////////////////////////////////////////////////////////////////////
+ // the body:
+ if (x.body) // compile the body if this is not a prototype
+ {
+ // Create a new basic block to start insertion into.
+ basic_block block = make_basic_block("entry", f);
+ set_insert_point(block);
+
+ function_allocas(x, f);
+ return_block = make_basic_block("return");
+
+ if (!(*this)(*x.body))
+ {
+ // Error reading body, remove function.
+ f.erase_from_parent();
+ return false;
+ }
+
+ basic_block last_block = f.last_block();
+
+ // If the last block is unterminated, connect it to return_block
+ if (!last_block.has_terminator())
+ {
+ set_insert_point(last_block);
+ branch(return_block);
+ }
+
+ f.add(return_block);
+ set_insert_point(return_block);
+
+ if (void_return)
+ return_();
+ else
+ return_(return_var);
+
+ // Validate the generated code, checking for consistency.
+ f.verify();
+
+ // Optimize the function.
+ optimize_function(f);
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ locals.clear(); // clear the variables
+ if (!(*this)(f))
+ return false;
+ }
+ return true;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp
new file mode 100644
index 00000000..ccca3644
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp
@@ -0,0 +1,311 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP)
+#define BOOST_SPIRIT_CONJURE_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include "vm.hpp"
+#include <map>
+
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+
+#include <llvm/DerivedTypes.h>
+#include <llvm/Constants.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Analysis/Passes.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Support/IRBuilder.h>
+
+namespace client { namespace code_gen
+{
+ unsigned const int_size = 32;
+ struct compiler;
+ struct llvm_compiler;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Value (light abstraction of an LLVM::Value)
+ ///////////////////////////////////////////////////////////////////////////
+ struct value
+ {
+ value();
+ value(value const& rhs);
+
+ value& operator=(value const& rhs);
+ bool is_lvalue() const;
+ bool is_valid() const;
+ operator bool() const;
+
+ value& assign(value const& rhs);
+
+ void name(char const* id);
+ void name(std::string const& id);
+
+ friend value operator-(value a);
+ friend value operator!(value a);
+ friend value operator+(value a, value b);
+ friend value operator-(value a, value b);
+ friend value operator*(value a, value b);
+ friend value operator/(value a, value b);
+ friend value operator%(value a, value b);
+
+ friend value operator&(value a, value b);
+ friend value operator|(value a, value b);
+ friend value operator^(value a, value b);
+ friend value operator<<(value a, value b);
+ friend value operator>>(value a, value b);
+
+ friend value operator==(value a, value b);
+ friend value operator!=(value a, value b);
+ friend value operator<(value a, value b);
+ friend value operator<=(value a, value b);
+ friend value operator>(value a, value b);
+ friend value operator>=(value a, value b);
+
+ private:
+
+ struct to_llvm_value;
+ friend struct to_llvm_value;
+ friend struct llvm_compiler;
+
+ value(
+ llvm::Value* v,
+ bool is_lvalue_,
+ llvm::IRBuilder<>* builder);
+
+ llvm::LLVMContext& context() const
+ { return llvm::getGlobalContext(); }
+
+ operator llvm::Value*() const;
+
+ llvm::Value* v;
+ bool is_lvalue_;
+ llvm::IRBuilder<>* builder;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Basic Block (light abstraction of an LLVM::BasicBlock)
+ ///////////////////////////////////////////////////////////////////////////
+ struct function;
+
+ struct basic_block
+ {
+ basic_block()
+ : b(0) {}
+
+ bool has_terminator() const;
+ bool is_valid() const;
+
+ private:
+
+ basic_block(llvm::BasicBlock* b)
+ : b(b) {}
+
+ operator llvm::BasicBlock*() const
+ { return b; }
+
+ friend struct llvm_compiler;
+ friend struct function;
+ llvm::BasicBlock* b;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Function (light abstraction of an LLVM::Function)
+ ///////////////////////////////////////////////////////////////////////////
+ struct llvm_compiler;
+
+ struct function
+ {
+ private:
+
+ struct to_value;
+ typedef llvm::Function::arg_iterator arg_iterator;
+ typedef boost::transform_iterator<
+ to_value, arg_iterator>
+ arg_val_iterator;
+
+ public:
+
+ typedef boost::iterator_range<arg_val_iterator> arg_range;
+
+ function()
+ : f(0), c(c) {}
+
+ std::string name() const;
+
+ std::size_t arg_size() const;
+ arg_range args() const;
+
+ void add(basic_block const& b);
+ void erase_from_parent();
+ basic_block last_block();
+ bool empty() const;
+
+ bool is_valid() const;
+ void verify() const;
+
+ private:
+
+ function(llvm::Function* f, llvm_compiler* c)
+ : f(f), c(c) {}
+
+ operator llvm::Function*() const;
+
+ friend struct llvm_compiler;
+ llvm::Function* f;
+ llvm_compiler* c;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The LLVM Compiler. Lower level compiler (does not deal with ASTs)
+ ///////////////////////////////////////////////////////////////////////////
+ struct llvm_compiler
+ {
+ llvm_compiler(vmachine& vm)
+ : llvm_builder(context())
+ , vm(vm)
+ , fpm(vm.module())
+ { init_fpm(); }
+
+ value val() { return value(); }
+ value val(unsigned int x);
+ value val(int x);
+ value val(bool x);
+
+ value var(char const* name);
+ value var(std::string const& name);
+
+ template <typename Container>
+ value call(function callee, Container const& args);
+
+ function get_function(char const* name);
+ function get_function(std::string const& name);
+ function get_current_function();
+
+ function declare_function(
+ bool void_return
+ , std::string const& name
+ , std::size_t nargs);
+
+ basic_block make_basic_block(
+ char const* name
+ , function parent = function()
+ , basic_block before = basic_block());
+
+ basic_block get_insert_block();
+ void set_insert_point(basic_block b);
+
+ void conditional_branch(
+ value cond, basic_block true_br, basic_block false_br);
+ void branch(basic_block b);
+
+ void return_();
+ void return_(value v);
+
+ void optimize_function(function f);
+
+ protected:
+
+ llvm::LLVMContext& context() const
+ { return llvm::getGlobalContext(); }
+
+ llvm::IRBuilder<>& builder()
+ { return llvm_builder; }
+
+ private:
+
+ friend struct function::to_value;
+
+ value val(llvm::Value* v);
+
+ template <typename C>
+ llvm::Value* call_impl(
+ function callee,
+ C const& args);
+
+ void init_fpm();
+ llvm::IRBuilder<> llvm_builder;
+ vmachine& vm;
+ llvm::FunctionPassManager fpm;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The main compiler. Generates code from our AST.
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler : llvm_compiler
+ {
+ typedef value result_type;
+
+ template <typename ErrorHandler>
+ compiler(vmachine& vm, ErrorHandler& error_handler_)
+ : llvm_compiler(vm)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ value operator()(ast::nil) { BOOST_ASSERT(0); return val(); }
+ value operator()(unsigned int x);
+ value operator()(bool x);
+ value operator()(ast::primary_expr const& x);
+ value operator()(ast::identifier const& x);
+ value operator()(ast::unary_expr const& x);
+ value operator()(ast::function_call const& x);
+ value operator()(ast::expression const& x);
+ value operator()(ast::assignment const& x);
+
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ private:
+
+ value compile_binary_expression(
+ value lhs, value rhs, token_ids::type op);
+
+ value compile_expression(
+ int min_precedence,
+ value lhs,
+ std::list<ast::operation>::const_iterator& rest_begin,
+ std::list<ast::operation>::const_iterator rest_end);
+
+ struct statement_compiler;
+ statement_compiler& as_statement();
+
+ function function_decl(ast::function const& x);
+ void function_allocas(ast::function const& x, function function);
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+
+ bool void_return;
+ std::string current_function_name;
+ std::map<std::string, value> locals;
+ basic_block return_block;
+ value return_var;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp
new file mode 100644
index 00000000..70af0db0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp
@@ -0,0 +1,51 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// The conjure lexer example can be built in 3 different variations:
+//
+// - With a lexer using runtime generated DFA tables
+// - With a lexer using pre-generated (static) DFA tables
+// - With a lexer using a pre-generated custom switch based state machine
+//
+// Use one of the following preprocessor constants to define, which of those
+// will be built:
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_DYNAMIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on pre-generated static DFA tables
+// #define CONJURE_LEXER_STATIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_STATIC_SWITCH 1
+
+///////////////////////////////////////////////////////////////////////////////
+// The default is to use the dynamic table driven lexer
+#if CONJURE_LEXER_DYNAMIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_SWITCH == 0
+
+#define CONJURE_LEXER_DYNAMIC_TABLES 1
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Make sure we have only one lexer type selected
+#if (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_TABLES != 0) || \
+ (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0) || \
+ (CONJURE_LEXER_STATIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0)
+
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp
new file mode 100644
index 00000000..651d34d6
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp
@@ -0,0 +1,483 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUL_25_2011_07_25_53)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUL_25_2011_07_25_53
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ enum {end_state_index, id_index, unique_id_index, state_index, bol_index,
+ eol_index, dead_state_index, dfa_offset};
+
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+ static std::size_t const lookup_[256] = {
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 7, 7, 41, 41, 7, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 7, 8, 41, 41, 41, 41, 9, 41,
+ 10, 11, 12, 13, 14, 15, 41, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 41, 19, 20, 21, 22, 41,
+ 41, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 41, 41, 41, 41, 18,
+ 41, 23, 18, 18, 24, 25, 26, 18,
+ 27, 28, 18, 18, 29, 18, 30, 31,
+ 18, 18, 32, 33, 34, 35, 36, 37,
+ 18, 18, 18, 38, 39, 40, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41 };
+ static std::size_t const dfa_alphabet_ = 42;
+ static std::size_t const dfa_[2604] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 27, 13, 11, 20, 21, 18, 16,
+ 24, 17, 19, 2, 26, 25, 14, 12,
+ 15, 26, 26, 7, 4, 26, 6, 26,
+ 26, 26, 9, 26, 3, 26, 5, 8,
+ 22, 10, 23, 0, 1, 35, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 28, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 29,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 30, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 32, 26,
+ 26, 26, 31, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 33, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 34, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 35, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 36, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 61, 26, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 262177, 20, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 39,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131091, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 40, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131093,
+ 14, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 41, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 393241, 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 393242, 17, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131099, 18, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131100,
+ 19, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 42, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 40, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 41, 22, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 123, 23, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 125,
+ 24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 44, 25, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 59, 27, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 34,
+ 30, 0, 0, 0, 0, 27, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 43, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 44,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 45, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 46, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65538, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 47, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 48, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 49, 26, 26, 26, 0, 0, 0, 0,
+ 1, 131084, 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 131085, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131089, 10, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131090,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 131092, 13, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 131094, 15, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 42, 42, 42, 42, 42,
+ 50, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 51,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 43, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 52, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65537, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 53,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 54, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 55, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 56, 56, 56, 56, 56,
+ 50, 56, 56, 56, 57, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 1, 36,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65536, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65539, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 58, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 59, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 33, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 65540, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 61, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 57, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 65541, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0 };
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
+ Iterator curr_ = start_token_;
+ bool end_state_ = *ptr_ != 0;
+ std::size_t id_ = *(ptr_ + id_index);
+ std::size_t uid_ = *(ptr_ + unique_id_index);
+ Iterator end_token_ = start_token_;
+
+ while (curr_ != end_)
+ {
+ std::size_t const state_ =
+ ptr_[lookup_[static_cast<unsigned char>(*curr_++)]];
+
+ if (state_ == 0) break;
+
+ ptr_ = &dfa_[state_ * dfa_alphabet_];
+
+ if (*ptr_)
+ {
+ end_state_ = true;
+ id_ = *(ptr_ + id_index);
+ uid_ = *(ptr_ + unique_id_index);
+ end_token_ = curr_;
+ }
+ }
+
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp
new file mode 100644
index 00000000..1ba8fac0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This small utility program generates the 2 static lexers, the static table
+// driven and the static switch based lexer.
+
+#include <fstream>
+#include <iostream>
+
+#include "lexer_def.hpp"
+#include <boost/spirit/include/lex_generate_static_lexertl.hpp>
+
+int main()
+{
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+
+ lexer_type lexer;
+
+ // first generate the static switch based lexer
+ std::ofstream out_static("conjure_static_switch_lexer.hpp");
+
+ bool result = boost::spirit::lex::lexertl::generate_static_switch(
+ lexer, out_static, "conjure_static_switch");
+ if (!result) {
+ std::cerr << "Failed to generate static switch based lexer\n";
+ return -1;
+ }
+
+ // now generate the static table based lexer
+ std::ofstream out("conjure_static_lexer.hpp");
+ result = boost::spirit::lex::lexertl::generate_static(
+ lexer, out, "conjure_static");
+ if (!result) {
+ std::cerr << "Failed to generate static table based lexer\n";
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp
new file mode 100644
index 00000000..0dcd1ac7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp
@@ -0,0 +1,873 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUL_25_2011_07_25_53)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUL_25_2011_07_25_53
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static_switch[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static_switch = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static_switch (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ Iterator curr_ = start_token_;
+ bool end_state_ = false;
+ std::size_t id_ = npos;
+ std::size_t uid_ = npos;
+ Iterator end_token_ = start_token_;
+
+ char ch_ = 0;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+
+ if (ch_ == 't') goto state0_2;
+
+ if (ch_ == 'f') goto state0_3;
+
+ if (ch_ == 'v') goto state0_4;
+
+ if (ch_ == 'i') goto state0_5;
+
+ if (ch_ == 'e') goto state0_6;
+
+ if (ch_ == 'w') goto state0_7;
+
+ if (ch_ == 'r') goto state0_8;
+
+ if (ch_ == '|') goto state0_9;
+
+ if (ch_ == '&') goto state0_10;
+
+ if (ch_ == '=') goto state0_11;
+
+ if (ch_ == '!') goto state0_12;
+
+ if (ch_ == '<') goto state0_13;
+
+ if (ch_ == '>') goto state0_14;
+
+ if (ch_ == '+') goto state0_15;
+
+ if (ch_ == '-') goto state0_16;
+
+ if (ch_ == '*') goto state0_17;
+
+ if (ch_ == '/') goto state0_18;
+
+ if (ch_ == '(') goto state0_19;
+
+ if (ch_ == ')') goto state0_20;
+
+ if (ch_ == '{') goto state0_21;
+
+ if (ch_ == '}') goto state0_22;
+
+ if (ch_ == ',') goto state0_23;
+
+ if (ch_ == ';') goto state0_24;
+
+ if ((ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'g' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'q') || ch_ == 's' || ch_ == 'u' || (ch_ >= 'x' && ch_ <= 'z')) goto state0_25;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_1:
+ end_state_ = true;
+ id_ = 35;
+ uid_ = 0;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+ goto end;
+
+state0_2:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_27;
+ goto end;
+
+state0_3:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'b' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'a') goto state0_28;
+ goto end;
+
+state0_4:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'n') || (ch_ >= 'p' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'o') goto state0_29;
+ goto end;
+
+state0_5:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'e') || (ch_ >= 'g' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_30;
+
+ if (ch_ == 'f') goto state0_31;
+ goto end;
+
+state0_6:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_32;
+ goto end;
+
+state0_7:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'g') || (ch_ >= 'i' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'h') goto state0_33;
+ goto end;
+
+state0_8:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_34;
+ goto end;
+
+state0_9:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '|') goto state0_35;
+ goto end;
+
+state0_10:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '&') goto state0_36;
+ goto end;
+
+state0_11:
+ end_state_ = true;
+ id_ = 61;
+ uid_ = 26;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_37;
+ goto end;
+
+state0_12:
+ end_state_ = true;
+ id_ = 262177;
+ uid_ = 20;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_38;
+ goto end;
+
+state0_13:
+ end_state_ = true;
+ id_ = 131091;
+ uid_ = 12;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_39;
+ goto end;
+
+state0_14:
+ end_state_ = true;
+ id_ = 131093;
+ uid_ = 14;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_40;
+ goto end;
+
+state0_15:
+ end_state_ = true;
+ id_ = 393241;
+ uid_ = 16;
+ end_token_ = curr_;
+ goto end;
+
+state0_16:
+ end_state_ = true;
+ id_ = 393242;
+ uid_ = 17;
+ end_token_ = curr_;
+ goto end;
+
+state0_17:
+ end_state_ = true;
+ id_ = 131099;
+ uid_ = 18;
+ end_token_ = curr_;
+ goto end;
+
+state0_18:
+ end_state_ = true;
+ id_ = 131100;
+ uid_ = 19;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_41;
+ goto end;
+
+state0_19:
+ end_state_ = true;
+ id_ = 40;
+ uid_ = 21;
+ end_token_ = curr_;
+ goto end;
+
+state0_20:
+ end_state_ = true;
+ id_ = 41;
+ uid_ = 22;
+ end_token_ = curr_;
+ goto end;
+
+state0_21:
+ end_state_ = true;
+ id_ = 123;
+ uid_ = 23;
+ end_token_ = curr_;
+ goto end;
+
+state0_22:
+ end_state_ = true;
+ id_ = 125;
+ uid_ = 24;
+ end_token_ = curr_;
+ goto end;
+
+state0_23:
+ end_state_ = true;
+ id_ = 44;
+ uid_ = 25;
+ end_token_ = curr_;
+ goto end;
+
+state0_24:
+ end_state_ = true;
+ id_ = 59;
+ uid_ = 27;
+ end_token_ = curr_;
+ goto end;
+
+state0_25:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_26:
+ end_state_ = true;
+ id_ = 34;
+ uid_ = 30;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_27:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_42;
+ goto end;
+
+state0_28:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_43;
+ goto end;
+
+state0_29:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_44;
+ goto end;
+
+state0_30:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_45;
+ goto end;
+
+state0_31:
+ end_state_ = true;
+ id_ = 65538;
+ uid_ = 4;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_32:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_46;
+ goto end;
+
+state0_33:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_47;
+ goto end;
+
+state0_34:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_48;
+ goto end;
+
+state0_35:
+ end_state_ = true;
+ id_ = 131084;
+ uid_ = 8;
+ end_token_ = curr_;
+ goto end;
+
+state0_36:
+ end_state_ = true;
+ id_ = 131085;
+ uid_ = 9;
+ end_token_ = curr_;
+ goto end;
+
+state0_37:
+ end_state_ = true;
+ id_ = 131089;
+ uid_ = 10;
+ end_token_ = curr_;
+ goto end;
+
+state0_38:
+ end_state_ = true;
+ id_ = 131090;
+ uid_ = 11;
+ end_token_ = curr_;
+ goto end;
+
+state0_39:
+ end_state_ = true;
+ id_ = 131092;
+ uid_ = 13;
+ end_token_ = curr_;
+ goto end;
+
+state0_40:
+ end_state_ = true;
+ id_ = 131094;
+ uid_ = 15;
+ end_token_ = curr_;
+ goto end;
+
+state0_41:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_41;
+
+ if (ch_ == '*') goto state0_49;
+ goto end;
+
+state0_42:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_50;
+ goto end;
+
+state0_43:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_42;
+ goto end;
+
+state0_44:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'c') || (ch_ >= 'e' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'd') goto state0_51;
+ goto end;
+
+state0_45:
+ end_state_ = true;
+ id_ = 65537;
+ uid_ = 3;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_46:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_52;
+ goto end;
+
+state0_47:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_53;
+ goto end;
+
+state0_48:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_54;
+ goto end;
+
+state0_49:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_49;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+ goto end;
+
+state0_50:
+ end_state_ = true;
+ id_ = 36;
+ uid_ = 1;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_51:
+ end_state_ = true;
+ id_ = 65536;
+ uid_ = 2;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_52:
+ end_state_ = true;
+ id_ = 65539;
+ uid_ = 5;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_53:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_57;
+ goto end;
+
+state0_54:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_58;
+ goto end;
+
+state0_55:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_55;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_56:
+ end_state_ = true;
+ id_ = 33;
+ uid_ = 29;
+ end_token_ = curr_;
+ goto end;
+
+state0_57:
+ end_state_ = true;
+ id_ = 65540;
+ uid_ = 6;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_58:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_60;
+ goto end;
+
+state0_59:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_60:
+ end_state_ = true;
+ id_ = 65541;
+ uid_ = 7;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+
+end:
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static_switch
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static_switch;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static_switch[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static_switch(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp
new file mode 100644
index 00000000..efda9a6a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp
@@ -0,0 +1,99 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator, typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(BaseIterator first, BaseIterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ // retrieve underlying iterator from current token, err_pos points
+ // to the last validly matched token, so we use its end iterator
+ // as the error position
+ BaseIterator err_pos_base = err_pos->matched().end();
+
+ int line;
+ BaseIterator line_start = get_pos(err_pos_base, line);
+ if (err_pos_base != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos_base; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ BaseIterator get_pos(BaseIterator err_pos, int& line) const
+ {
+ line = 1;
+ BaseIterator i = first;
+ BaseIterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(BaseIterator err_pos) const
+ {
+ BaseIterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ BaseIterator first;
+ BaseIterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp
new file mode 100644
index 00000000..5b51ce36
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::expression<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp
new file mode 100644
index 00000000..eec9cd6a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp
@@ -0,0 +1,59 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CONJURE_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct expression : qi::grammar<Iterator, ast::expression()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ expression(error_handler_type& error_handler, Lexer const& l);
+
+ Lexer const& lexer;
+
+ qi::rule<Iterator, ast::expression()> expr;
+ qi::rule<Iterator, ast::operand()> unary_expr, postfix_expr;
+ qi::rule<Iterator, ast::function_call()> function_call;
+ qi::rule<Iterator, std::list<ast::expression>()> argument_list;
+ qi::rule<Iterator, std::string()> identifier;
+ qi::rule<Iterator, ast::primary_expr()> primary_expr;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp
new file mode 100644
index 00000000..2d21323a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp
@@ -0,0 +1,104 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/lex_plain_token.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ expression<Iterator, Lexer>::expression(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : expression::base_type(expr), lexer(l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::tokenid_mask_type tokenid_mask;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ unary_expr
+ >> *(tokenid_mask(token_ids::op_binary) > unary_expr)
+ ;
+
+ unary_expr =
+ postfix_expr
+ | (tokenid_mask(token_ids::op_unary) > unary_expr)
+ ;
+
+ postfix_expr =
+ function_call
+ | primary_expr
+ ;
+
+ primary_expr =
+ lexer.lit_uint
+ | lexer.true_or_false
+ | identifier
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier = lexer.identifier;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (unary_expr)
+ (postfix_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in unary_expr, postfix_expr,
+ // and primary_expr call annotation.
+ on_success(unary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(postfix_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp
new file mode 100644
index 00000000..98c8169b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "function_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::function<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp
new file mode 100644
index 00000000..fc5263f1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp
@@ -0,0 +1,36 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_FUNCTION_HPP)
+#define BOOST_SPIRIT_CONJURE_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct function : qi::grammar<Iterator, ast::function()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ function(error_handler_type& error_handler, Lexer const& l);
+
+ statement<Iterator, Lexer> body;
+
+ qi::rule<Iterator, ast::identifier()> identifier;
+ qi::rule<Iterator, std::list<ast::identifier>()> argument_list;
+ qi::rule<Iterator, ast::function()> start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp
new file mode 100644
index 00000000..95846264
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp
@@ -0,0 +1,64 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ function<Iterator, Lexer>::function(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : function::base_type(start), body(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ identifier = body.expr.identifier;
+ argument_list = -(identifier % ',');
+
+ start = (l.token("void") | l.token("int"))
+ > identifier
+ > '(' > argument_list > ')'
+ > (';' | '{' > body > '}')
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp
new file mode 100644
index 00000000..c4d98acc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp
@@ -0,0 +1,160 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_IDS_HPP)
+#define BOOST_SPIRIT_CONJURE_IDS_HPP
+
+namespace client
+{
+ struct op_type
+ {
+ enum type
+ {
+ binary = 0x20000,
+ unary = 0x40000,
+ postfix_unary = 0x80000,
+ assign = 0x100000
+ };
+ };
+
+ struct op
+ {
+ enum type
+ {
+ // binary
+ comma,
+ assign,
+ plus_assign,
+ minus_assign,
+ times_assign,
+ divide_assign,
+ mod_assign,
+ bit_and_assign,
+ bit_xor_assign,
+ bit_or_assign,
+ shift_left_assign,
+ shift_right_assign,
+ logical_or,
+ logical_and,
+ bit_or,
+ bit_xor,
+ bit_and,
+ equal,
+ not_equal,
+ less,
+ less_equal,
+ greater,
+ greater_equal,
+ shift_left,
+ shift_right,
+ plus,
+ minus,
+ times,
+ divide,
+ mod,
+
+ // unary
+ plus_plus,
+ minus_minus,
+ compl_,
+ not_,
+ };
+ };
+
+ template <int type, int op>
+ struct make_op
+ {
+ static int const value = type + op;
+ };
+
+ template <op::type op>
+ struct unary_op : make_op<op_type::unary, op> {};
+
+ template <op::type op>
+ struct binary_op
+ : make_op<op_type::binary, op> {};
+
+ template <op::type op>
+ struct assign_op
+ : make_op<op_type::assign, op> {};
+
+ template <op::type op>
+ struct binary_or_unary_op
+ : make_op<op_type::unary | op_type::binary, op> {};
+
+ struct token_ids
+ {
+ enum type
+ {
+ // pseudo tags
+ invalid = -1,
+ op_binary = op_type::binary,
+ op_unary = op_type::unary,
+ op_assign = op_type::assign,
+
+ // binary / unary operators with common tokens
+ // '+' and '-' can be binary or unary
+ // (the lexer cannot distinguish which)
+ plus = binary_or_unary_op<op::plus>::value,
+ minus = binary_or_unary_op<op::minus>::value,
+
+ // binary operators
+ comma = binary_op<op::comma>::value,
+ assign = assign_op<op::assign>::value,
+ plus_assign = assign_op<op::plus_assign>::value,
+ minus_assign = assign_op<op::minus_assign>::value,
+ times_assign = assign_op<op::times_assign>::value,
+ divide_assign = assign_op<op::divide_assign>::value,
+ mod_assign = assign_op<op::mod_assign>::value,
+ bit_and_assign = assign_op<op::bit_and_assign>::value,
+ bit_xor_assign = assign_op<op::bit_xor_assign>::value,
+ bit_or_assign = assign_op<op::bit_or_assign>::value,
+ shift_left_assign = assign_op<op::shift_left_assign>::value,
+ shift_right_assign = assign_op<op::shift_right_assign>::value,
+ logical_or = binary_op<op::logical_or>::value,
+ logical_and = binary_op<op::logical_and>::value,
+ bit_or = binary_op<op::bit_or>::value,
+ bit_xor = binary_op<op::bit_xor>::value,
+ bit_and = binary_op<op::bit_and>::value,
+ equal = binary_op<op::equal>::value,
+ not_equal = binary_op<op::not_equal>::value,
+ less = binary_op<op::less>::value,
+ less_equal = binary_op<op::less_equal>::value,
+ greater = binary_op<op::greater>::value,
+ greater_equal = binary_op<op::greater_equal>::value,
+ shift_left = binary_op<op::shift_left>::value,
+ shift_right = binary_op<op::shift_right>::value,
+ times = binary_op<op::times>::value,
+ divide = binary_op<op::divide>::value,
+ mod = binary_op<op::mod>::value,
+
+ // unary operators with overlaps
+ // '++' and '--' can be prefix or postfix
+ // (the lexer cannot distinguish which)
+ plus_plus = make_op<
+ op_type::unary
+ | op_type::postfix_unary, op::plus_plus>::value,
+
+ minus_minus = make_op<
+ op_type::unary
+ | op_type::postfix_unary, op::minus_minus>::value,
+
+ // unary operators
+ compl_ = unary_op<op::compl_>::value,
+ not_ = unary_op<op::not_>::value,
+
+ // misc tags
+ identifier = op::not_ + 1,
+ comment,
+ whitespace,
+ lit_uint,
+ true_or_false
+ };
+ };
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp
new file mode 100644
index 00000000..d7125fed
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp
@@ -0,0 +1,17 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+template client::lexer::conjure_tokens<base_iterator_type>::conjure_tokens();
+template bool client::lexer::conjure_tokens<base_iterator_type>::add_(
+ std::string const&, int);
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp
new file mode 100644
index 00000000..9624fe2f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp
@@ -0,0 +1,144 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_HPP
+
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/lex_lexertl_position_token.hpp>
+
+#include "config.hpp"
+#include "ids.hpp"
+
+#if CONJURE_LEXER_STATIC_TABLES != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_lexer.hpp"
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_switch_lexer.hpp"
+#endif
+#include <boost/assert.hpp>
+
+namespace client { namespace lexer
+{
+ namespace lex = boost::spirit::lex;
+
+ ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ namespace lex = boost::spirit::lex;
+
+ template <typename BaseIterator>
+ struct get_lexer_type
+ {
+ // Our token needs to be able to carry several token values:
+ // std::string, unsigned int, and bool
+ typedef boost::mpl::vector<std::string, unsigned int, bool>
+ token_value_types;
+
+ // Using the position_token class as the token type to be returned
+ // from the lexer iterators allows to retain positional information
+ // as every token instance stores an iterator pair pointing to the
+ // matched input sequence.
+ typedef lex::lexertl::position_token<
+ BaseIterator, token_value_types, boost::mpl::false_
+ > token_type;
+
+#if CONJURE_LEXER_DYNAMIC_TABLES != 0
+ // use the lexer based on runtime generated DFA tables
+ typedef lex::lexertl::actor_lexer<token_type> type;
+#elif CONJURE_LEXER_STATIC_TABLES != 0
+ // use the lexer based on pre-generated static DFA tables
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static
+ > type;
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+ // use the lexer based on pre-generated static code
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static_switch
+ > type;
+#else
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator>
+ struct conjure_tokens
+ : lex::lexer<typename detail::get_lexer_type<BaseIterator>::type>
+ {
+ private:
+ // get the type of any qi::raw_token(...) and qi::token(...) constructs
+ typedef typename boost::spirit::result_of::terminal<
+ boost::spirit::tag::raw_token(token_ids::type)
+ >::type raw_token_spec;
+
+ typedef typename boost::spirit::result_of::terminal<
+ boost::spirit::tag::token(token_ids::type)
+ >::type token_spec;
+
+ typedef std::map<std::string, token_ids::type> keyword_map_type;
+
+ protected:
+ // add a keyword to the mapping table
+ bool add_(std::string const& keyword, int id = token_ids::invalid);
+
+ struct keyword_adder
+ {
+ conjure_tokens& l;
+ keyword_adder(conjure_tokens& l) : l(l) {}
+ keyword_adder& operator()(
+ std::string const& keyword, int id = token_ids::invalid)
+ {
+ l.add_(keyword, id);
+ return *this;
+ }
+ };
+
+ friend struct keyword_adder;
+ keyword_adder add;
+
+ public:
+ typedef BaseIterator base_iterator_type;
+
+ conjure_tokens();
+
+ // extract a raw_token(id) for the given registered keyword
+ raw_token_spec operator()(std::string const& kwd) const
+ {
+ namespace qi = boost::spirit::qi;
+ qi::raw_token_type raw_token;
+
+ typename keyword_map_type::const_iterator it = keywords_.find(kwd);
+ BOOST_ASSERT(it != keywords_.end());
+ return raw_token((it != keywords_.end()) ? (*it).second : token_ids::invalid);
+ }
+
+ // extract a token(id) for the given registered keyword
+ token_spec token(std::string const& kwd) const
+ {
+ namespace qi = boost::spirit::qi;
+ qi::token_type token;
+
+ typename keyword_map_type::const_iterator it = keywords_.find(kwd);
+ BOOST_ASSERT(it != keywords_.end());
+ return token((it != keywords_.end()) ? (*it).second : token_ids::invalid);
+ }
+
+ lex::token_def<std::string> identifier;
+ lex::token_def<unsigned int> lit_uint;
+ lex::token_def<bool> true_or_false;
+ keyword_map_type keywords_;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp
new file mode 100644
index 00000000..29239768
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp
@@ -0,0 +1,100 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "lexer.hpp"
+
+namespace client { namespace lexer
+{
+ template <typename BaseIterator>
+ conjure_tokens<BaseIterator>::conjure_tokens()
+ : identifier("[a-zA-Z_][a-zA-Z_0-9]*", token_ids::identifier)
+ , lit_uint("[0-9]+", token_ids::lit_uint)
+ , true_or_false("true|false", token_ids::true_or_false)
+ , add(*this)
+ {
+ lex::_pass_type _pass;
+
+ this->self = lit_uint | true_or_false;
+
+ this->add
+ ("void")
+ ("int")
+ ("if")
+ ("else")
+ ("while")
+ ("return")
+ ("=", token_ids::assign)
+ ("\\+=", token_ids::plus_assign)
+ ("\\-=", token_ids::minus_assign)
+ ("\\*=", token_ids::times_assign)
+ ("\\/=", token_ids::divide_assign)
+ ("%=", token_ids::mod_assign)
+ ("\\&=", token_ids::bit_and_assign)
+ ("\\^=", token_ids::bit_xor_assign)
+ ("\\|=", token_ids::bit_or_assign)
+ ("<<=", token_ids::shift_left_assign)
+ (">>=", token_ids::shift_right_assign)
+ ("\\|\\|", token_ids::logical_or)
+ ("&&", token_ids::logical_and)
+ ("\\|", token_ids::bit_or)
+ ("\\^", token_ids::bit_xor)
+ ("&", token_ids::bit_and)
+ ("<<", token_ids::shift_left)
+ (">>", token_ids::shift_right)
+ ("==", token_ids::equal)
+ ("!=", token_ids::not_equal)
+ ("<", token_ids::less)
+ ("<=", token_ids::less_equal)
+ (">", token_ids::greater)
+ (">=", token_ids::greater_equal)
+ ("\\+", token_ids::plus)
+ ("\\-", token_ids::minus)
+ ("\\*", token_ids::times)
+ ("\\/", token_ids::divide)
+ ("%", token_ids::mod)
+ ("\\+\\+", token_ids::plus_plus)
+ ("\\-\\-", token_ids::minus_minus)
+ ("~", token_ids::compl_)
+ ("!", token_ids::not_)
+ ;
+
+ this->self += lex::char_('(') | ')' | '{' | '}' | ',' | ';';
+
+ this->self +=
+ identifier
+ | lex::string("(\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/)|(\\/\\/[^\r\n]*)", token_ids::comment)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ | lex::string("[ \t\n\r]+", token_ids::whitespace)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ ;
+ }
+
+ template <typename BaseIterator>
+ bool conjure_tokens<BaseIterator>::add_(
+ std::string const& keyword, int id_)
+ {
+ // add the token to the lexer
+ token_ids::type id;
+ if (id_ == token_ids::invalid)
+ id = token_ids::type(this->get_next_id());
+ else
+ id = token_ids::type(id_);
+
+ this->self.add(keyword, id);
+ // store the mapping for later retrieval
+ std::pair<typename keyword_map_type::iterator, bool> p =
+ keywords_.insert(typename keyword_map_type::value_type(keyword, id));
+
+ return p.second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp
new file mode 100644
index 00000000..9788e56f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp
@@ -0,0 +1,156 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ HK June 3, 2011 ] Adding lexer
+// [ JDG July 18, 2011 ] Switching to LLVM backend
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "config.hpp"
+#include "function.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include "lexer.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+ typedef lexer_type::iterator_type iterator_type;
+
+ lexer_type lexer; // Our lexer
+
+ base_iterator_type first = source_code.begin();
+ base_iterator_type last = source_code.end();
+
+ iterator_type iter = lexer.begin(first, last);
+ iterator_type end = lexer.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<base_iterator_type, iterator_type>
+ error_handler(first, last); // Our error handler
+ client::parser::function<iterator_type, lexer_type>
+ function(error_handler, lexer); // Our parser
+ client::code_gen::compiler
+ compiler(vm, error_handler); // Our compiler
+
+ // note: we don't need a skipper
+ bool success = parse(iter, end, +function, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ // JIT the main function
+ client::function main_function = vm.get_function("main");
+ if (!main_function)
+ {
+ std::cerr << "function main not found" << std::endl;
+ return 1;
+ }
+
+ int nargs = argc-2;
+ if (main_function.arity() != nargs)
+ {
+ std::cerr << "Error: main function requires "
+ << main_function.arity() << " arguments." << std::endl;
+ std::cerr << nargs << " supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ vm.print_assembler();
+
+ // Call the main function
+ int r;
+ char** args = argv + 2;
+ switch (nargs)
+ {
+ case 0: r = main_function(); break;
+
+ case 1: r = main_function(
+ boost::lexical_cast<int>(args[0]));
+ break;
+
+ case 2: r = main_function(
+ boost::lexical_cast<int>(args[0]),
+ boost::lexical_cast<int>(args[1]));
+ break;
+
+ case 3: r = main_function(
+ boost::lexical_cast<int>(args[0]),
+ boost::lexical_cast<int>(args[1]),
+ boost::lexical_cast<int>(args[2]));
+ break;
+
+ default:
+ std::cerr << "Function calls with more " <<
+ "than 3 arguments not supported" << std::endl;
+ return 1;
+ }
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp
new file mode 100644
index 00000000..ca85a61c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::statement<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp
new file mode 100644
index 00000000..208ca247
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp
@@ -0,0 +1,42 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_STATEMENT_HPP)
+#define BOOST_SPIRIT_CONJURE_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct statement : qi::grammar<Iterator, ast::statement_list()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ statement(error_handler_type& error_handler, Lexer const& l);
+
+ expression<Iterator, Lexer> expr;
+
+ qi::rule<Iterator, ast::statement_list()>
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement()> statement_;
+ qi::rule<Iterator, ast::variable_declaration()> variable_declaration;
+ qi::rule<Iterator, ast::assignment()> assignment;
+ qi::rule<Iterator, ast::if_statement()> if_statement;
+ qi::rule<Iterator, ast::while_statement()> while_statement;
+ qi::rule<Iterator, ast::return_statement()> return_statement;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp
new file mode 100644
index 00000000..4712aa5f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp
@@ -0,0 +1,126 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ statement<Iterator, Lexer>::statement(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : statement::base_type(statement_list), expr(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::tokenid_mask_type tokenid_mask;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ | expr
+ | ';'
+ ;
+
+ variable_declaration =
+ l("int")
+ > expr.identifier
+ > -(l("=") > expr)
+ > ';'
+ ;
+
+ assignment =
+ expr.identifier
+ > tokenid_mask(token_ids::op_assign)
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ l("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ l("else")
+ > statement_
+ )
+ ;
+
+ while_statement =
+ l("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ l("return")
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (statement_)
+ (variable_declaration)
+ (assignment)
+ (if_statement)
+ (while_statement)
+ (compound_statement)
+ (return_statement)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in variable_declaration,
+ // assignment and return_statement, call annotation.
+ on_success(variable_declaration,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp
new file mode 100644
index 00000000..5434046f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp
@@ -0,0 +1,43 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "config.hpp"
+#include "vm.hpp"
+#include <iostream>
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ vmachine::vmachine()
+ {
+ llvm::InitializeNativeTarget();
+ llvm::LLVMContext& context = llvm::getGlobalContext();
+
+ // Make the module, which holds all the code.
+ module_ = new llvm::Module("Conjure JIT", context);
+
+ // Create the JIT. This takes ownership of the module.
+ std::string error;
+ execution_engine_ =
+ llvm::EngineBuilder(module_).setErrorStr(&error).create();
+
+ BOOST_ASSERT(execution_engine_ != 0);
+ if (!execution_engine_)
+ {
+ std::cerr <<
+ "Could not create ExecutionEngine: " <<
+ error << std::endl;
+
+ exit(1);
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp
new file mode 100644
index 00000000..68698920
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_VM_HPP)
+#define BOOST_SPIRIT_CONJURE_VM_HPP
+
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Target/TargetSelect.h>
+
+#include <boost/assert.hpp>
+
+namespace client
+{
+ class vmachine;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // A light wrapper to a function pointer returning int and accepting
+ // from 0 to 3 arguments, where arity is determined at runtime.
+ ///////////////////////////////////////////////////////////////////////////
+ class function
+ {
+ public:
+
+ typedef int result_type;
+
+ int operator()() const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 0);
+ int (*fp)() = (int(*)())(intptr_t)fptr;
+ return fp();
+ }
+
+ int operator()(int _1) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 1);
+ int (*fp)(int) = (int(*)(int))(intptr_t)fptr;
+ return fp(_1);
+ }
+
+ int operator()(int _1, int _2) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 2);
+ int (*fp)(int, int) = (int(*)(int, int))(intptr_t)fptr;
+ return fp(_1, _2);
+ }
+
+ int operator()(int _1, int _2, int _3) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 3);
+ int (*fp)(int, int, int) = (int(*)(int, int, int))(intptr_t)fptr;
+ return fp(_1, _2, _3);
+ }
+
+ unsigned arity() const { return arity_; }
+ bool operator!() const { return fptr == 0; }
+
+ private:
+
+ friend class vmachine;
+ function(void* fptr, unsigned arity_)
+ : fptr(fptr), arity_(arity_) {}
+
+ void* fptr;
+ unsigned arity_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine (light wrapper over LLVM JIT)
+ ///////////////////////////////////////////////////////////////////////////
+ class vmachine
+ {
+ public:
+
+ vmachine();
+
+ llvm::Module* module() const
+ {
+ return module_;
+ }
+
+ llvm::ExecutionEngine* execution_engine() const
+ {
+ return execution_engine_;
+ }
+
+ void print_assembler() const
+ {
+ module_->dump();
+ }
+
+ function get_function(char const* name)
+ {
+ llvm::Function* callee = module_->getFunction(name);
+ if (callee == 0)
+ return function(0, 0);
+
+ // JIT the function
+ void *fptr = execution_engine_->getPointerToFunction(callee);
+ return function(fptr, callee->arg_size());
+ }
+
+ private:
+
+ llvm::Module* module_;
+ llvm::ExecutionEngine* execution_engine_;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/error.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/error.cnj
new file mode 100644
index 00000000..2c7c0a94
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/error.cnj
@@ -0,0 +1,16 @@
+/* conjure program with syntax error */
+
+int foo(n)
+{
+ int a = 2;
+ if (n @ 3) /* we don't have @ operator in conjure */
+ {
+ a = 3
+ }
+ return a;
+}
+
+int main()
+{
+ return foo(10);
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/factorial.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/factorial.cnj
new file mode 100644
index 00000000..5ea05731
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/factorial.cnj
@@ -0,0 +1,15 @@
+/* The factorial */
+
+int factorial(n)
+{
+ if (n <= 0)
+ return 1;
+ else
+ return n * factorial(n-1);
+}
+
+int main(n)
+{
+ return factorial(n);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/operators.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/operators.cnj
new file mode 100644
index 00000000..8f8aad56
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/operators.cnj
@@ -0,0 +1,137 @@
+/* More operators tests */
+/* Conjure >=3 only!!! */
+
+// assign ops
+
+int aplus(x, y)
+{
+ int t = x;
+ t += y;
+ return t;
+}
+
+int aminus(x, y)
+{
+ int t = x;
+ t -= y;
+ return t;
+}
+
+int ashl(x, y)
+{
+ int t = x;
+ t <<= y;
+ return t;
+}
+
+int adiv(x, y)
+{
+ int t = x;
+ t /= y;
+ return t;
+}
+
+int amult(x, y)
+{
+ int t = x;
+ t *= y;
+ return t;
+}
+
+int amod(x, y)
+{
+ int t = x;
+ t %= y;
+ return t;
+}
+
+int aor(x, y)
+{
+ int t = x;
+ t |= y;
+ return t;
+}
+
+int aand(x, y)
+{
+ int t = x;
+ t &= y;
+ return t;
+}
+
+int axor(x, y)
+{
+ int t = x;
+ t ^= y;
+ return t;
+}
+
+int ashr(x, y)
+{
+ int t = x;
+ t >>= y;
+ return t;
+}
+
+// binary ops
+
+int plus(x, y) { return x + y; }
+int minus(x, y) { return x - y; }
+int shl(x, y) { return x << y; }
+int div(x, y) { return x / y; }
+int mult(x, y) { return x * y; }
+int mod(x, y) { return x % y; }
+int or(x, y) { return x | y; }
+int and(x, y) { return x & y; }
+int xor(x, y) { return x ^ y; }
+int shr(x, y) { return x >> y; }
+
+int assign()
+{
+ int a = aplus(2, 3); // 5
+ int b = ashl(a, 2); // 20
+ int c = aminus(b, 2); // 18
+ int d = adiv(c, 2); // 9
+ int e = amult(d, c); // 162
+ int f = amod(e, 10); // 2
+ int g = aor(f, 45); // 47
+ int h = aand(g, 48); // 32
+ int j = axor(h, h); // 0
+ int k = aor(j, 65535); // 65535
+ int l = ashr(k, 3); // 8191
+ return l;
+}
+
+int binary()
+{
+ int a = plus(2, 3); // 5
+ int b = shl(a, 2); // 20
+ int c = minus(b, 2); // 18
+ int d = div(c, 2); // 9
+ int e = mult(d, c); // 162
+ int f = mod(e, 10); // 2
+ int g = or(f, 45); // 47
+ int h = and(g, 48); // 32
+ int j = xor(h, h); // 0
+ int k = or(j, 65535); // 65535
+ int l = shr(k, 3); // 8191
+ return l;
+}
+
+int zero() { return 0; }
+
+int unary()
+{
+ int i = ~zero(); // -1
+ int j = -i; // 1
+ ++j; // 2
+ ++++j; // 4
+ --j; // 3
+ return j;
+}
+
+int main()
+{
+ return assign() + binary() + unary(); // 16385
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/pow2.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/pow2.cnj
new file mode 100644
index 00000000..4d22fd70
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/pow2.cnj
@@ -0,0 +1,19 @@
+/* My first conjure program */
+
+int pow2(n)
+{
+ int a = 2;
+ int i = 1;
+ while (i < n)
+ {
+ a = a * 2;
+ i = i + 1;
+ }
+ return a;
+}
+
+int main()
+{
+ return pow2(10);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/precedence.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/precedence.cnj
new file mode 100644
index 00000000..eb91b92e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/precedence.cnj
@@ -0,0 +1,8 @@
+/* testing the shunting yard operator precedence algorithm */
+
+int main()
+{
+ return 1 + 2 + 3 + 5 * 4 * 6 + 5; /* answer is 131 */
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/annotation.hpp
new file mode 100644
index 00000000..9e7e814e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/annotation.hpp
@@ -0,0 +1,95 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_ANNOTATION_HPP)
+#define BOOST_SPIRIT_MINIC_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ void operator()(ast::identifier& x) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ // no-op
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::variable_declaration& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/ast.hpp
new file mode 100644
index 00000000..fc755064
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/ast.hpp
@@ -0,0 +1,225 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_AST_HPP)
+#define BOOST_SPIRIT_MINIC_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<function_call>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ enum optoken
+ {
+ op_plus,
+ op_minus,
+ op_times,
+ op_divide,
+ op_positive,
+ op_negative,
+ op_not,
+ op_equal,
+ op_not_equal,
+ op_less,
+ op_less_equal,
+ op_greater,
+ op_greater_equal,
+ op_and,
+ op_or
+ };
+
+ struct unary
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ statement_list body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (client::ast::statement_list, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.cpp
new file mode 100644
index 00000000..5a17ee07
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.cpp
@@ -0,0 +1,538 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void function::op(int a)
+ {
+ code.push_back(a);
+ size_ += 1;
+ }
+
+ void function::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ size_ += 2;
+ }
+
+ void function::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ size_ += 3;
+ }
+
+ int const* function::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void function::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void function::link_to(std::string const& name, std::size_t address)
+ {
+ function_calls[address] = name;
+ }
+
+ void function::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin() + address;
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << " local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != (code.begin() + address + size_))
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_call:
+ {
+ line += " op_call ";
+ int nargs = *pc++;
+ std::size_t jump = *pc++;
+ line += boost::lexical_cast<std::string>(nargs) + ", ";
+ BOOST_ASSERT(function_calls.find(jump) != function_calls.end());
+ line += function_calls.find(jump)->second;
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+
+ case op_return:
+ line += " op_return";
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ typedef std::pair<std::size_t, std::string> line_info;
+ BOOST_FOREACH(line_info const& l, lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::identifier const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.name);
+ if (p == 0)
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ current->op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::operation const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_plus: current->op(op_add); break;
+ case ast::op_minus: current->op(op_sub); break;
+ case ast::op_times: current->op(op_mul); break;
+ case ast::op_divide: current->op(op_div); break;
+
+ case ast::op_equal: current->op(op_eq); break;
+ case ast::op_not_equal: current->op(op_neq); break;
+ case ast::op_less: current->op(op_lt); break;
+ case ast::op_less_equal: current->op(op_lte); break;
+ case ast::op_greater: current->op(op_gt); break;
+ case ast::op_greater_equal: current->op(op_gte); break;
+
+ case ast::op_and: current->op(op_and); break;
+ case ast::op_or: current->op(op_or); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_negative: current->op(op_neg); break;
+ case ast::op_not: current->op(op_not); break;
+ case ast::op_positive: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_call const& x)
+ {
+ BOOST_ASSERT(current != 0);
+
+ if (functions.find(x.function_name.name) == functions.end())
+ {
+ error_handler(x.function_name.id, "Function not found: " + x.function_name.name);
+ return false;
+ }
+
+ boost::shared_ptr<code_gen::function> p = functions[x.function_name.name];
+
+ if (p->nargs() != x.args.size())
+ {
+ error_handler(x.function_name.id, "Wrong number of arguments: " + x.function_name.name);
+ return false;
+ }
+
+ BOOST_FOREACH(ast::expression const& expr, x.args)
+ {
+ if (!(*this)(expr))
+ return false;
+ }
+
+ current->op(
+ op_call,
+ p->nargs(),
+ p->get_address());
+ current->link_to(x.function_name.name, p->get_address());
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ BOOST_FOREACH(ast::operation const& oper, x.rest)
+ {
+ if (!(*this)(oper))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = current->find_var(x.lhs.name);
+ if (p == 0)
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ current->op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.lhs.name);
+ if (p != 0)
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+ if (x.rhs) // if there's an RHS initializer
+ {
+ bool r = (*this)(*x.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ current->add_var(x.lhs.name);
+ current->op(op_store, *current->find_var(x.lhs.name));
+ }
+ return r;
+ }
+ else
+ {
+ current->add_var(x.lhs.name);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = current->size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ (*current)[skip] = current->size()-skip; // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an else
+ {
+ (*current)[skip] += 2; // adjust for the "else" jump
+ current->op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ (*current)[exit] = current->size()-exit;// now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ std::size_t loop = current->size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ current->op(op_jump,
+ int(loop-1) - int(current->size())); // loop back
+ (*current)[exit] = current->size()-exit; // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(x.id, current_function_name + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ if (!(*this)(*x.expr))
+ return false;
+ }
+ current->op(op_return);
+ return true;
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ if (functions.find(x.function_name.name) != functions.end())
+ {
+ error_handler(x.function_name.id, "Duplicate function: " + x.function_name.name);
+ return false;
+ }
+ boost::shared_ptr<code_gen::function>& p = functions[x.function_name.name];
+ p.reset(new code_gen::function(code, x.args.size()));
+ current = p.get();
+ current_function_name = x.function_name.name;
+
+ // op_stk_adj 0 for now. we'll know how many variables
+ // we'll have later and add them
+ current->op(op_stk_adj, 0);
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ current->add_var(arg.name);
+ }
+
+ if (!(*this)(x.body))
+ return false;
+ (*current)[1] = current->nvars(); // now store the actual number of variables
+ // this includes the arguments
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ // Jump to the main function
+ code.push_back(op_jump);
+ code.push_back(0); // we will fill this in later when we finish compiling
+ // and we know where the main function is
+
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ if (!(*this)(f))
+ {
+ code.clear();
+ return false;
+ }
+ }
+ // find the main function
+ boost::shared_ptr<code_gen::function> p =
+ find_function("main");
+
+ if (!p) // main function not found
+ {
+ std::cerr << "Error: main function not defined" << std::endl;
+ return false;
+ }
+ code[1] = p->get_address()-1; // jump to this (main function) address
+
+ return true;
+ }
+
+ void compiler::print_assembler() const
+ {
+ typedef std::pair<std::string, boost::shared_ptr<code_gen::function> > pair;
+ BOOST_FOREACH(pair const& p, functions)
+ {
+ std::cout << ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" << std::endl;
+ std::cout << p.second->get_address() << ": function " << p.first << std::endl;
+ p.second->print_assembler();
+ }
+ }
+
+ boost::shared_ptr<code_gen::function>
+ compiler::find_function(std::string const& name) const
+ {
+ function_table::const_iterator i = functions.find(name);
+ if (i == functions.end())
+ return boost::shared_ptr<code_gen::function>();
+ else
+ return i->second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.hpp
new file mode 100644
index 00000000..8a3eea72
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.hpp
@@ -0,0 +1,118 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_COMPILER_HPP)
+#define BOOST_SPIRIT_MINIC_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Function
+ ///////////////////////////////////////////////////////////////////////////
+ struct function
+ {
+ function(std::vector<int>& code, int nargs)
+ : code(code), address(code.size()), size_(0), nargs_(nargs) {}
+
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[address+i]; }
+ int const& operator[](std::size_t i) const { return code[address+i]; }
+ std::size_t size() const { return size_; }
+ std::size_t get_address() const { return address; }
+
+ int nargs() const { return nargs_; }
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+ void link_to(std::string const& name, std::size_t address);
+
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::map<std::size_t, std::string> function_calls;
+ std::vector<int>& code;
+ std::size_t address;
+ std::size_t size_;
+ std::size_t nargs_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(ErrorHandler& error_handler_)
+ : current(0)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x);
+ bool operator()(bool x);
+ bool operator()(ast::identifier const& x);
+ bool operator()(ast::operation const& x);
+ bool operator()(ast::unary const& x);
+ bool operator()(ast::function_call const& x);
+ bool operator()(ast::expression const& x);
+ bool operator()(ast::assignment const& x);
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ void print_assembler() const;
+
+ boost::shared_ptr<code_gen::function>
+ find_function(std::string const& name) const;
+
+ std::vector<int>& get_code() { return code; }
+ std::vector<int> const& get_code() const { return code; }
+
+ private:
+
+ typedef std::map<std::string, boost::shared_ptr<code_gen::function> > function_table;
+
+ std::vector<int> code;
+ code_gen::function* current;
+ std::string current_function_name;
+ function_table functions;
+ bool void_return;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/error_handler.hpp
new file mode 100644
index 00000000..4ba833c6
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/error_handler.hpp
@@ -0,0 +1,93 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_MINIC_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ if (err_pos != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.cpp
new file mode 100644
index 00000000..32f44adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::expression<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.hpp
new file mode 100644
index 00000000..60edceec
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.hpp
@@ -0,0 +1,79 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_EXPRESSION_HPP)
+#define BOOST_SPIRIT_MINIC_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include "skipper.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct expression : qi::grammar<Iterator, ast::expression(), skipper<Iterator> >
+ {
+ expression(error_handler<Iterator>& error_handler);
+
+ qi::rule<Iterator, ast::expression(), skipper<Iterator> >
+ expr, equality_expr, relational_expr,
+ logical_or_expr, logical_and_expr,
+ additive_expr, multiplicative_expr
+ ;
+
+ qi::rule<Iterator, ast::operand(), skipper<Iterator> >
+ unary_expr, primary_expr
+ ;
+
+ qi::rule<Iterator, ast::function_call(), skipper<Iterator> >
+ function_call
+ ;
+
+ qi::rule<Iterator, std::list<ast::expression>(), skipper<Iterator> >
+ argument_list
+ ;
+
+ qi::rule<Iterator, std::string(), skipper<Iterator> >
+ identifier
+ ;
+
+ qi::symbols<char, ast::optoken>
+ logical_or_op, logical_and_op,
+ equality_op, relational_op,
+ additive_op, multiplicative_op, unary_op
+ ;
+
+ qi::symbols<char>
+ keywords
+ ;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression_def.hpp
new file mode 100644
index 00000000..f6f7c5d6
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression_def.hpp
@@ -0,0 +1,181 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
+ : expression::base_type(expr)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::bool_type bool_;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tokens
+ logical_or_op.add
+ ("||", ast::op_or)
+ ;
+
+ logical_and_op.add
+ ("&&", ast::op_and)
+ ;
+
+ equality_op.add
+ ("==", ast::op_equal)
+ ("!=", ast::op_not_equal)
+ ;
+
+ relational_op.add
+ ("<", ast::op_less)
+ ("<=", ast::op_less_equal)
+ (">", ast::op_greater)
+ (">=", ast::op_greater_equal)
+ ;
+
+ additive_op.add
+ ("+", ast::op_plus)
+ ("-", ast::op_minus)
+ ;
+
+ multiplicative_op.add
+ ("*", ast::op_times)
+ ("/", ast::op_divide)
+ ;
+
+ unary_op.add
+ ("+", ast::op_positive)
+ ("-", ast::op_negative)
+ ("!", ast::op_not)
+ ;
+
+ keywords.add
+ ("true")
+ ("false")
+ ("if")
+ ("else")
+ ("while")
+ ("int")
+ ("void")
+ ("return")
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ logical_or_expr.alias()
+ ;
+
+ logical_or_expr =
+ logical_and_expr
+ >> *(logical_or_op > logical_and_expr)
+ ;
+
+ logical_and_expr =
+ equality_expr
+ >> *(logical_and_op > equality_expr)
+ ;
+
+ equality_expr =
+ relational_expr
+ >> *(equality_op > relational_expr)
+ ;
+
+ relational_expr =
+ additive_expr
+ >> *(relational_op > additive_expr)
+ ;
+
+ additive_expr =
+ multiplicative_expr
+ >> *(additive_op > multiplicative_expr)
+ ;
+
+ multiplicative_expr =
+ unary_expr
+ >> *(multiplicative_op > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (unary_op > unary_expr)
+ ;
+
+ primary_expr =
+ uint_
+ | function_call
+ | identifier
+ | bool_
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier =
+ !lexeme[keywords >> !(alnum | '_')]
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (logical_or_expr)
+ (logical_and_expr)
+ (equality_expr)
+ (relational_expr)
+ (additive_expr)
+ (multiplicative_expr)
+ (unary_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.cpp
new file mode 100644
index 00000000..ababd4ad
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "function_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::function<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.hpp
new file mode 100644
index 00000000..cef1c82d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_FUNCTION_HPP)
+#define BOOST_SPIRIT_MINIC_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct function : qi::grammar<Iterator, ast::function(), skipper<Iterator> >
+ {
+ function(error_handler<Iterator>& error_handler);
+
+ statement<Iterator> body;
+ qi::rule<Iterator, std::string(), skipper<Iterator> > name;
+ qi::rule<Iterator, ast::identifier(), skipper<Iterator> > identifier;
+ qi::rule<Iterator, std::list<ast::identifier>(), skipper<Iterator> > argument_list;
+ qi::rule<Iterator, ast::function(), skipper<Iterator> > start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function_def.hpp
new file mode 100644
index 00000000..bd2c7d02
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function_def.hpp
@@ -0,0 +1,71 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ function<Iterator>::function(error_handler<Iterator>& error_handler)
+ : function::base_type(start), body(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::string_type string;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ name =
+ !body.expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ identifier = name;
+ argument_list = -(identifier % ',');
+
+ start =
+ lexeme[(string("void") | string("int"))
+ >> !(alnum | '_')] // make sure we have whole words
+ > identifier
+ > '(' > argument_list > ')'
+ > '{' > body > '}'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/main.cpp
new file mode 100644
index 00000000..27d4bee0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/main.cpp
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "function.hpp"
+#include "skipper.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source_code.begin();
+ iterator_type end = source_code.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::parser::function<iterator_type>
+ function(error_handler); // Our parser
+ client::parser::skipper<iterator_type>
+ skipper; // Our skipper
+ client::code_gen::compiler
+ compiler(error_handler); // Our compiler
+
+
+ bool success = phrase_parse(iter, end, +function, skipper, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ boost::shared_ptr<client::code_gen::function>
+ p = compiler.find_function("main");
+ if (!p)
+ return 1;
+
+ int nargs = argc-2;
+ if (p->nargs() != nargs)
+ {
+ std::cerr << "Error: main function requires " << p->nargs() << " arguments." << std::endl;
+ std::cerr << nargs << "supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ compiler.print_assembler();
+
+ // Push the arguments into our stack
+ for (int i = 0; i < nargs; ++i)
+ vm.get_stack()[i] = boost::lexical_cast<int>(argv[i+2]);
+
+ // Call the interpreter
+ int r = vm.execute(compiler.get_code());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/skipper.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/skipper.hpp
new file mode 100644
index 00000000..041fb9b0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/skipper.hpp
@@ -0,0 +1,40 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_SKIPPER_HPP)
+#define BOOST_SPIRIT_MINIC_SKIPPER_HPP
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The skipper grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct skipper : qi::grammar<Iterator>
+ {
+ skipper() : skipper::base_type(start)
+ {
+ qi::char_type char_;
+ ascii::space_type space;
+
+ start =
+ space // tab/space/cr/lf
+ | "/*" >> *(char_ - "*/") >> "*/" // C-style comments
+ ;
+ }
+
+ qi::rule<Iterator> start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.cpp
new file mode 100644
index 00000000..54bc9ac3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::statement<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.hpp
new file mode 100644
index 00000000..366f8741
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.hpp
@@ -0,0 +1,38 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_STATEMENT_HPP)
+#define BOOST_SPIRIT_MINIC_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement_list(), skipper<Iterator> >
+ {
+ statement(error_handler<Iterator>& error_handler);
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement_list(), skipper<Iterator> >
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement(), skipper<Iterator> > statement_;
+ qi::rule<Iterator, ast::variable_declaration(), skipper<Iterator> > variable_declaration;
+ qi::rule<Iterator, ast::assignment(), skipper<Iterator> > assignment;
+ qi::rule<Iterator, ast::if_statement(), skipper<Iterator> > if_statement;
+ qi::rule<Iterator, ast::while_statement(), skipper<Iterator> > while_statement;
+ qi::rule<Iterator, ast::return_statement(), skipper<Iterator> > return_statement;
+ qi::rule<Iterator, std::string(), skipper<Iterator> > identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement_def.hpp
new file mode 100644
index 00000000..f99b665a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement_def.hpp
@@ -0,0 +1,124 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(statement_list), expr(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::lit_type lit;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ ;
+
+ identifier =
+ !expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ lexeme["int" >> !(alnum | '_')] // make sure we have whole words
+ > identifier
+ > -('=' > expr)
+ > ';'
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ lit("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ lexeme["else" >> !(alnum | '_')] // make sure we have whole words
+ > statement_
+ )
+ ;
+
+ while_statement =
+ lit("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ lexeme["return" >> !(alnum | '_')] // make sure we have whole words
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (identifier)
+ (variable_declaration)
+ (assignment)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in variable_declaration,
+ // assignment and return_statement, call annotation.
+ on_success(variable_declaration,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.cpp
new file mode 100644
index 00000000..8740bf9c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.cpp
@@ -0,0 +1,159 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ 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 "vm.hpp"
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (true)
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr += *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.hpp
new file mode 100644
index 00000000..eb4cc294
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.hpp
@@ -0,0 +1,82 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_VM_HPP)
+#define BOOST_SPIRIT_MINIC_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ }
+
+ std::vector<int> const& get_stack() const { return stack; };
+ std::vector<int>& get_stack() { return stack; };
+
+ private:
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/1.mini b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/1.mini
new file mode 100644
index 00000000..bd22c869
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/1.mini
@@ -0,0 +1,19 @@
+/* My first mini program */
+
+int pow2(n)
+{
+ int a = 2;
+ int i = 1;
+ while (i < n)
+ {
+ a = a * 2;
+ i = i + 1;
+ }
+ return a;
+}
+
+int main()
+{
+ return pow2(10);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/2.mini b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/2.mini
new file mode 100644
index 00000000..5ea05731
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/2.mini
@@ -0,0 +1,15 @@
+/* The factorial */
+
+int factorial(n)
+{
+ if (n <= 0)
+ return 1;
+ else
+ return n * factorial(n-1);
+}
+
+int main(n)
+{
+ return factorial(n);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/3.mini b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/3.mini
new file mode 100644
index 00000000..5c407d6e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/3.mini
@@ -0,0 +1,17 @@
+/* mini program with syntax error */
+
+int foo(n)
+{
+ int a = 2;
+ if (n @ 3) /* we don't have @ operator in mini_c */
+ {
+ a = 3
+ }
+ return a;
+}
+
+int main()
+{
+ return foo(10);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/complex_number.cpp b/src/boost/libs/spirit/example/qi/complex_number.cpp
new file mode 100644
index 00000000..a4400e0c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/complex_number.cpp
@@ -0,0 +1,101 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A complex number micro parser.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG May 9, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+///////////////////////////////////////////////////////////////////////////////
+// Our complex number parser/compiler
+///////////////////////////////////////////////////////////////////////////////
+//[tutorial_complex_number
+namespace client
+{
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+ using boost::phoenix::ref;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ '(' >> double_[ref(rN) = _1]
+ >> -(',' >> double_[ref(iN) = _1]) >> ')'
+ | double_[ref(rN) = _1]
+ ),
+ // End grammar
+
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+}
+//]
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << c << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/custom_string.cpp b/src/boost/libs/spirit/example/qi/custom_string.cpp
new file mode 100644
index 00000000..e5e78221
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/custom_string.cpp
@@ -0,0 +1,113 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example demonstrates the steps needed to integrate a custom container
+// type to be usable with Spirit.Qi. It shows how to utilize the QString data
+// type as a Qi attribute.
+
+// Note: you need to have Qt4 installed on your system and you have to make
+// sure your compiler finds the includes and your linker finds the
+// proper libraries.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+
+#include <Qt/qstring.h>
+
+namespace boost { namespace spirit { namespace traits
+{
+ // Make Qi recognize QString as a container
+ template <> struct is_container<QString> : mpl::true_ {};
+
+ // Expose the container's (QString's) value_type
+ template <> struct container_value<QString> : mpl::identity<QChar> {};
+
+ // Define how to insert a new element at the end of the container (QString)
+ template <>
+ struct push_back_container<QString, QChar>
+ {
+ static bool call(QString& c, QChar const& val)
+ {
+ c.append(val);
+ return true;
+ }
+ };
+
+ // Test if a QString is empty (required for debug)
+ template <>
+ struct is_empty_container<QString>
+ {
+ static bool call(QString const& c)
+ {
+ return c.isEmpty();
+ }
+ };
+
+ // Define how to stream a QString (required for debug)
+ template <typename Out, typename Enable>
+ struct print_attribute_debug<Out, QString, Enable>
+ {
+ static void call(Out& out, QString const& val)
+ {
+ out << val.toStdString();
+ }
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ template <typename Iterator>
+ bool parse_qstring(Iterator first, Iterator last, QString& t)
+ {
+ using boost::spirit::qi::char_;
+ using boost::spirit::ascii::space;
+ using boost::spirit::qi::phrase_parse;
+
+ bool r = phrase_parse(first, last, +char_, space, t);
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+
+ return r;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tParsing into a QString from Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ QString t;
+ if (client::parse_qstring(str.begin(), str.end(), t))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << t.toStdString() << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/display_attribute_type.cpp b/src/boost/libs/spirit/example/qi/display_attribute_type.cpp
new file mode 100644
index 00000000..11f086b5
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/display_attribute_type.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example implements a simple utility allowing to print the attribute
+// type as it is exposed by an arbitrary Qi parser expression. Just insert
+// your expression below, compile and run this example to see what Qi is
+// seeing!
+
+#include "display_attribute_type.hpp"
+
+namespace qi = boost::spirit::qi;
+
+int main()
+{
+ tools::display_attribute_of_parser(
+ std::cerr, // put the required output stream here
+ qi::int_ >> qi::double_ // put your parser expression here
+ );
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/display_attribute_type.hpp b/src/boost/libs/spirit/example/qi/display_attribute_type.hpp
new file mode 100644
index 00000000..84c2245d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/display_attribute_type.hpp
@@ -0,0 +1,59 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example implements a simple utility allowing to print the attribute
+// type as it is exposed by an arbitrary Qi parser expression. Just insert
+// your expression below, compile and run this example to see what Qi is
+// seeing!
+
+#if !defined (DISPLAY_ATTRIBUTE_OF_PARSER_JAN_2010_30_0722PM)
+#define DISPLAY_ATTRIBUTE_OF_PARSER_JAN_2010_30_0722PM
+
+#include <iostream>
+#include <boost/spirit/include/qi.hpp>
+
+namespace tools
+{
+ namespace spirit = boost::spirit;
+
+ template <typename Expr, typename Iterator = spirit::unused_type>
+ struct attribute_of_parser
+ {
+ typedef typename spirit::result_of::compile<
+ spirit::qi::domain, Expr
+ >::type parser_expression_type;
+
+ typedef typename spirit::traits::attribute_of<
+ parser_expression_type, spirit::unused_type, Iterator
+ >::type type;
+ };
+
+ template <typename T>
+ void display_attribute_of_parser(T const &)
+ {
+ // Report invalid expression error as early as possible.
+ // If you got an error_invalid_expression error message here,
+ // then the expression (expr) is not a valid spirit qi expression.
+ BOOST_SPIRIT_ASSERT_MATCH(spirit::qi::domain, T);
+
+ typedef typename attribute_of_parser<T>::type type;
+ std::cout << typeid(type).name() << std::endl;
+ }
+
+ template <typename T>
+ void display_attribute_of_parser(std::ostream& os, T const &)
+ {
+ // Report invalid expression error as early as possible.
+ // If you got an error_invalid_expression error message here,
+ // then the expression (expr) is not a valid spirit qi expression.
+ BOOST_SPIRIT_ASSERT_MATCH(spirit::qi::domain, T);
+
+ typedef typename attribute_of_parser<T>::type type;
+ os << typeid(type).name() << std::endl;
+ }
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/employee.cpp b/src/boost/libs/spirit/example/qi/employee.cpp
new file mode 100644
index 00000000..c303ff8b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/employee.cpp
@@ -0,0 +1,151 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A parser for arbitrary tuples. This example presents a parser
+// for an employee structure.
+//
+// [ JDG May 9, 2007 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our employee struct
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_employee_struct
+ struct employee
+ {
+ int age;
+ std::string surname;
+ std::string forename;
+ double salary;
+ };
+ //]
+}
+
+// We need to tell fusion about our employee struct
+// to make it a first-class fusion citizen. This has to
+// be in global scope.
+
+//[tutorial_employee_adapt_struct
+BOOST_FUSION_ADAPT_STRUCT(
+ client::employee,
+ (int, age)
+ (std::string, surname)
+ (std::string, forename)
+ (double, salary)
+)
+//]
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our employee parser
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_employee_parser
+ template <typename Iterator>
+ struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
+ {
+ employee_parser() : employee_parser::base_type(start)
+ {
+ using qi::int_;
+ using qi::lit;
+ using qi::double_;
+ using qi::lexeme;
+ using ascii::char_;
+
+ quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
+
+ start %=
+ lit("employee")
+ >> '{'
+ >> int_ >> ','
+ >> quoted_string >> ','
+ >> quoted_string >> ','
+ >> double_
+ >> '}'
+ ;
+ }
+
+ qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
+ qi::rule<Iterator, employee(), ascii::space_type> start;
+ };
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tAn employee parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout
+ << "Give me an employee of the form :"
+ << "employee{age, \"surname\", \"forename\", salary } \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ using boost::spirit::ascii::space;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::employee_parser<iterator_type> employee_parser;
+
+ employee_parser g; // Our grammar
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::employee emp;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, g, space, emp);
+
+ if (r && iter == end)
+ {
+ std::cout << boost::fusion::tuple_open('[');
+ std::cout << boost::fusion::tuple_close(']');
+ std::cout << boost::fusion::tuple_delimiter(", ");
+
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/expect.cpp b/src/boost/libs/spirit/example/qi/expect.cpp
new file mode 100644
index 00000000..ecbc24aa
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/expect.cpp
@@ -0,0 +1,112 @@
+/*=============================================================================
+Copyright (c) 2016 Frank Hein, maxence business consulting gmbh
+
+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 <iostream>
+#include <map>
+
+#include <boost/spirit/home/qi.hpp>
+#include <boost/spirit/home/qi/nonterminal/grammar.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+#include <boost/foreach.hpp>
+
+namespace qi = boost::spirit::qi;
+
+typedef std::string::const_iterator iterator_type;
+typedef std::string result_type;
+
+template<typename Parser>
+void parse(const std::string message, const std::string& input, const std::string& rule, const Parser& parser) {
+ iterator_type iter = input.begin(), end = input.end();
+
+ std::vector<result_type> parsed_result;
+
+ std::cout << "-------------------------\n";
+ std::cout << message << "\n";
+ std::cout << "Rule: " << rule << std::endl;
+ std::cout << "Parsing: \"" << input << "\"\n";
+
+ bool result = qi::phrase_parse(iter, end, parser, qi::space, parsed_result);
+ if (result)
+ {
+ std::cout << "Parser succeeded.\n";
+ std::cout << "Parsed " << parsed_result.size() << " elements:";
+ BOOST_FOREACH(result_type const& str, parsed_result)
+ {
+ std::cout << "[" << str << "]";
+ }
+ std::cout << std::endl;
+ }
+ else
+ {
+ std::cout << "Parser failed" << std::endl;
+ }
+ if (iter == end) {
+ std::cout << "EOI reached." << std::endl;
+ }
+ else {
+ std::cout << "EOI not reached. Unparsed: \"" << std::string(iter, end) << "\"" << std::endl;
+ }
+ std::cout << "-------------------------\n";
+
+}
+
+namespace grammars {
+ namespace phx = boost::phoenix;
+
+ template <typename Iterator>
+ struct ident : qi::grammar < Iterator, std::string(), qi::space_type>
+ {
+ ident();
+
+ qi::rule <iterator_type, std::string(), qi::space_type>
+ id, id_list, qualified_id;
+ };
+
+ template <typename Iterator>
+ ident<Iterator>::ident() : ident::base_type(id_list) {
+
+ using qi::on_error;
+ using qi::fail;
+ using qi::expect;
+
+ id = (qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_'));
+
+ id_list = expect[id >> qi::lit(';')];
+
+ on_error<fail>(id_list,
+ phx::ref(std::cout)
+ << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl
+ << "Error! Expecting "
+ << qi::_4
+ << " here: "
+ << phx::construct<std::string>(qi::_3, qi::_2) << std::endl
+ << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl
+ );
+ }
+}
+
+int main() {
+
+ grammars::ident<iterator_type> id;
+
+ parse("expect directive, fail on first"
+ , "1234; id2;"
+ , "qi::expect[ id >> qi::lit(';') ]"
+ , id);
+
+ parse("expect directive, fail on second"
+ , "id1, id2"
+ , "qi::expect[ id >> qi::lit(';') ]"
+ , id);
+
+ parse("expect directive, success"
+ , "id1;"
+ , "qi::expect[ id >> qi::lit(';') ]"
+ , id);
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/german_floating_point.cpp b/src/boost/libs/spirit/example/qi/german_floating_point.cpp
new file mode 100644
index 00000000..c091ca92
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/german_floating_point.cpp
@@ -0,0 +1,48 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+// Copyright (c) 2011 Michael Caisse
+//
+// 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 <boost/spirit/include/qi.hpp>
+
+namespace qi = boost::spirit::qi;
+
+template <typename T>
+struct german_real_policies : qi::real_policies<T>
+{
+ template <typename Iterator>
+ static bool parse_dot(Iterator& first, Iterator const& last)
+ {
+ if (first == last || *first != ',')
+ return false;
+ ++first;
+ return true;
+ }
+};
+
+qi::real_parser<double, german_real_policies<double> > const german_double;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::string input("123,456");
+ std::string::iterator begin = input.begin();
+ std::string::iterator end = input.end();
+
+ double value = 0;
+ if (!qi::parse(begin, end, german_double, value))
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded, got: " << value << "\n";
+ std::cout << "---------------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/iter_pos.hpp b/src/boost/libs/spirit/example/qi/iter_pos.hpp
new file mode 100644
index 00000000..b6259fd7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/iter_pos.hpp
@@ -0,0 +1,83 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(ITER_POS_NOV_20_2009_1245PM)
+#define ITER_POS_NOV_20_2009_1245PM
+
+#include <boost/spirit/include/qi_parse.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// definition the place holder
+namespace custom_parser
+{
+ BOOST_SPIRIT_TERMINAL(iter_pos)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// implementation the enabler
+namespace boost { namespace spirit
+{
+ // We want custom_parser::iter_pos to be usable as a terminal only,
+ // and only for parser expressions (qi::domain).
+ template <>
+ struct use_terminal<qi::domain, custom_parser::tag::iter_pos>
+ : mpl::true_
+ {};
+}}
+
+///////////////////////////////////////////////////////////////////////////////
+// implementation of the parser
+namespace custom_parser
+{
+ struct iter_pos_parser
+ : boost::spirit::qi::primitive_parser<iter_pos_parser>
+ {
+ // Define the attribute type exposed by this parser component
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ typedef Iterator type;
+ };
+
+ // This function is called during the actual parsing process
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context&, Skipper const& skipper, Attribute& attr) const
+ {
+ boost::spirit::qi::skip_over(first, last, skipper);
+ boost::spirit::traits::assign_to(first, attr);
+ return true;
+ }
+
+ // This function is called during error handling to create
+ // a human readable string for the error context.
+ template <typename Context>
+ boost::spirit::info what(Context&) const
+ {
+ return boost::spirit::info("iter_pos");
+ }
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// instantiation of the parser
+namespace boost { namespace spirit { namespace qi
+{
+ // This is the factory function object invoked in order to create
+ // an instance of our iter_pos_parser.
+ template <typename Modifiers>
+ struct make_primitive<custom_parser::tag::iter_pos, Modifiers>
+ {
+ typedef custom_parser::iter_pos_parser result_type;
+
+ result_type operator()(unused_type, unused_type) const
+ {
+ return result_type();
+ }
+ };
+}}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/iter_pos_parser.cpp b/src/boost/libs/spirit/example/qi/iter_pos_parser.cpp
new file mode 100644
index 00000000..92ff4b00
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/iter_pos_parser.cpp
@@ -0,0 +1,51 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how a simple custom primitive parser
+// component can be written. We develop a custom parser exposing the current
+// iterator position as its attribute.
+//
+// For more information see: http://spirit.sourceforge.net/home/?page_id=567
+
+#include <boost/spirit/include/qi_parse_attr.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+
+#include <string>
+#include "iter_pos.hpp"
+
+namespace qi = boost::spirit::qi;
+
+int main()
+{
+ using custom_parser::iter_pos;
+
+ std::string prefix, suffix; // attributes receiving the
+ std::string::iterator position; // parsed values
+
+ std::string input("prefix1234567");
+ std::string::iterator first = input.begin();
+ bool result =
+ qi::parse(first, input.end()
+ , +qi::alpha >> iter_pos >> +qi::digit
+ , prefix, position, suffix);
+
+ if (result)
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "prefix is: " << prefix << "\n";
+ std::cout << "suffix is: " << suffix << "\n";
+ std::cout << "position is: " << std::distance(input.begin(), position) << "\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/key_value_sequence.cpp b/src/boost/libs/spirit/example/qi/key_value_sequence.cpp
new file mode 100644
index 00000000..3e75786d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/key_value_sequence.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how to parse arbitrary key/value
+// pairs delimited by some separator into a std::map. Parsing the URL query
+// format is the example we use to demonstrate how this can be done
+// (i.e. things like: key1=value1;key2=value2;...;keyN=valueN).
+//
+// For a more elaborate explanation see here: http://spirit.sourceforge.net/home/?p=371
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <map>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ typedef std::map<std::string, std::string> pairs_type;
+
+ template <typename Iterator>
+ struct key_value_sequence
+ : qi::grammar<Iterator, pairs_type()>
+ {
+ key_value_sequence()
+ : key_value_sequence::base_type(query)
+ {
+ query = pair >> *((qi::lit(';') | '&') >> pair);
+ pair = key >> -('=' >> value);
+ key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
+ value = +qi::char_("a-zA-Z_0-9");
+ }
+
+ qi::rule<Iterator, pairs_type()> query;
+ qi::rule<Iterator, std::pair<std::string, std::string>()> pair;
+ qi::rule<Iterator, std::string()> key, value;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace qi = boost::spirit::qi;
+
+ std::string input("key1=value1;key2;key3=value3");
+ std::string::iterator begin = input.begin();
+ std::string::iterator end = input.end();
+
+ client::key_value_sequence<std::string::iterator> p;
+ client::pairs_type m;
+
+ if (!qi::parse(begin, end, p, m))
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded, found entries:\n";
+ client::pairs_type::iterator end = m.end();
+ for (client::pairs_type::iterator it = m.begin(); it != end; ++it)
+ {
+ std::cout << (*it).first;
+ if (!(*it).second.empty())
+ std::cout << "=" << (*it).second;
+ std::cout << std::endl;
+ }
+ std::cout << "---------------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp b/src/boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp
new file mode 100644
index 00000000..8cb8e20d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp
@@ -0,0 +1,83 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how to parse arbitrary key/value
+// pairs delimited by some separator into a std::vector. The difference to
+// the example 'key_value_sequence.cpp' is that we preserve the order of the
+// elements in the parsed sequence as well as possibly existing duplicates.
+// In addition to the example 'key_value_sequence_ordered.cpp' we allow for
+// empty values, i.e. the grammar allows to distinguish between 'key=;' and
+// 'key;", where the first stores an empty string as the value, while the
+// second does not initialize the optional holding the value.
+//
+// For a more elaborate explanation see here: http://spirit.sourceforge.net/home/?p=371
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <map>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ typedef std::pair<std::string, boost::optional<std::string> > pair_type;
+ typedef std::vector<pair_type> pairs_type;
+
+ template <typename Iterator>
+ struct key_value_sequence_empty_value
+ : qi::grammar<Iterator, pairs_type()>
+ {
+ key_value_sequence_empty_value()
+ : key_value_sequence_empty_value::base_type(query)
+ {
+ query = pair >> *((qi::lit(';') | '&') >> pair);
+ pair = key >> -('=' >> -value);
+ key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
+ value = +qi::char_("a-zA-Z_0-9");
+ }
+
+ qi::rule<Iterator, pairs_type()> query;
+ qi::rule<Iterator, pair_type()> pair;
+ qi::rule<Iterator, std::string()> key, value;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace qi = boost::spirit::qi;
+
+ std::string input("key1=value1;key2;key3=value3;key4=");
+ std::string::iterator begin = input.begin();
+ std::string::iterator end = input.end();
+
+ client::key_value_sequence_empty_value<std::string::iterator> p;
+ client::pairs_type m;
+
+ if (!qi::parse(begin, end, p, m))
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded, found entries:\n";
+ client::pairs_type::iterator end = m.end();
+ for (client::pairs_type::iterator it = m.begin(); it != end; ++it)
+ {
+ std::cout << (*it).first;
+ if ((*it).second)
+ std::cout << "=" << boost::get<std::string>((*it).second);
+ std::cout << std::endl;
+ }
+ std::cout << "---------------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/key_value_sequence_ordered.cpp b/src/boost/libs/spirit/example/qi/key_value_sequence_ordered.cpp
new file mode 100644
index 00000000..21689239
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/key_value_sequence_ordered.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how to parse arbitrary key/value
+// pairs delimited by some separator into a std::vector. The difference to
+// the example 'key_value_sequence.cpp' is that we preserve the order of the
+// elements in the parsed seqeunce as well as possibly existing duplicates.
+//
+// For a more elaborate explanation see here: http://spirit.sourceforge.net/home/?p=371
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <map>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ typedef std::vector<std::pair<std::string, std::string> > pairs_type;
+
+ template <typename Iterator>
+ struct key_value_sequence_ordered
+ : qi::grammar<Iterator, pairs_type()>
+ {
+ key_value_sequence_ordered()
+ : key_value_sequence_ordered::base_type(query)
+ {
+ query = pair >> *((qi::lit(';') | '&') >> pair);
+ pair = key >> -('=' >> value);
+ key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
+ value = +qi::char_("a-zA-Z_0-9");
+ }
+
+ qi::rule<Iterator, pairs_type()> query;
+ qi::rule<Iterator, std::pair<std::string, std::string>()> pair;
+ qi::rule<Iterator, std::string()> key, value;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace qi = boost::spirit::qi;
+
+ std::string input("key2=value2;key1;key3=value3");
+ std::string::iterator begin = input.begin();
+ std::string::iterator end = input.end();
+
+ client::key_value_sequence_ordered<std::string::iterator> p;
+ client::pairs_type v;
+
+ if (!qi::parse(begin, end, p, v))
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded, found entries:\n";
+ client::pairs_type::iterator end = v.end();
+ for (client::pairs_type::iterator it = v.begin(); it != end; ++it)
+ {
+ std::cout << (*it).first;
+ if (!(*it).second.empty())
+ std::cout << "=" << (*it).second;
+ std::cout << std::endl;
+ }
+ std::cout << "---------------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/mini_xml1.cpp b/src/boost/libs/spirit/example/qi/mini_xml1.cpp
new file mode 100644
index 00000000..1a27eda4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml1.cpp
@@ -0,0 +1,242 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A mini XML-like parser
+//
+// [ JDG March 25, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace fusion = boost::fusion;
+ namespace phoenix = boost::phoenix;
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML tree representation
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_xml1_structures
+ struct mini_xml;
+
+ typedef
+ boost::variant<
+ boost::recursive_wrapper<mini_xml>
+ , std::string
+ >
+ mini_xml_node;
+
+ struct mini_xml
+ {
+ std::string name; // tag name
+ std::vector<mini_xml_node> children; // children
+ };
+ //]
+}
+
+// We need to tell fusion about our mini_xml struct
+// to make it a first-class fusion citizen
+//[tutorial_xml1_adapt_structures
+BOOST_FUSION_ADAPT_STRUCT(
+ client::mini_xml,
+ (std::string, name)
+ (std::vector<client::mini_xml_node>, children)
+)
+//]
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Print out the mini xml tree
+ ///////////////////////////////////////////////////////////////////////////
+ int const tabsize = 4;
+
+ void tab(int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ std::cout << ' ';
+ }
+
+ struct mini_xml_printer
+ {
+ mini_xml_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const;
+
+ int indent;
+ };
+
+ struct mini_xml_node_printer : boost::static_visitor<>
+ {
+ mini_xml_node_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const
+ {
+ mini_xml_printer(indent+tabsize)(xml);
+ }
+
+ void operator()(std::string const& text) const
+ {
+ tab(indent+tabsize);
+ std::cout << "text: \"" << text << '"' << std::endl;
+ }
+
+ int indent;
+ };
+
+ void mini_xml_printer::operator()(mini_xml const& xml) const
+ {
+ tab(indent);
+ std::cout << "tag: " << xml.name << std::endl;
+ tab(indent);
+ std::cout << '{' << std::endl;
+
+ BOOST_FOREACH(mini_xml_node const& node, xml.children)
+ {
+ boost::apply_visitor(mini_xml_node_printer(indent), node);
+ }
+
+ tab(indent);
+ std::cout << '}' << std::endl;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML grammar definition
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_xml1_grammar
+ template <typename Iterator>
+ struct mini_xml_grammar : qi::grammar<Iterator, mini_xml(), ascii::space_type>
+ {
+ mini_xml_grammar() : mini_xml_grammar::base_type(xml)
+ {
+ using qi::lit;
+ using qi::lexeme;
+ using ascii::char_;
+ using ascii::string;
+ using namespace qi::labels;
+
+ using phoenix::at_c;
+ using phoenix::push_back;
+
+ text = lexeme[+(char_ - '<') [_val += _1]];
+ node = (xml | text) [_val = _1];
+
+ start_tag =
+ '<'
+ >> !lit('/')
+ >> lexeme[+(char_ - '>') [_val += _1]]
+ >> '>'
+ ;
+
+ end_tag =
+ "</"
+ >> lit(_r1)
+ >> '>'
+ ;
+
+ xml =
+ start_tag [at_c<0>(_val) = _1]
+ >> *node [push_back(at_c<1>(_val), _1)]
+ >> end_tag(at_c<0>(_val))
+ ;
+ }
+
+ qi::rule<Iterator, mini_xml(), ascii::space_type> xml;
+ qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
+ qi::rule<Iterator, std::string(), ascii::space_type> text;
+ qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
+ qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
+ };
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string storage; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(storage));
+
+ typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar;
+ mini_xml_grammar xml; // Our grammar
+ client::mini_xml ast; // Our tree
+
+ using boost::spirit::ascii::space;
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = phrase_parse(iter, end, xml, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ client::mini_xml_printer printer;
+ printer(ast);
+ return 0;
+ }
+ else
+ {
+ std::string::const_iterator some = iter + std::min(30, int(end - iter));
+ std::string context(iter, (some>end)?end:some);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << context << "...\"\n";
+ std::cout << "-------------------------\n";
+ return 1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/mini_xml2.cpp b/src/boost/libs/spirit/example/qi/mini_xml2.cpp
new file mode 100644
index 00000000..6d56374b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml2.cpp
@@ -0,0 +1,237 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A mini XML-like parser
+//
+// [ JDG March 25, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace fusion = boost::fusion;
+ namespace phoenix = boost::phoenix;
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML tree representation
+ ///////////////////////////////////////////////////////////////////////////
+ struct mini_xml;
+
+ typedef
+ boost::variant<
+ boost::recursive_wrapper<mini_xml>
+ , std::string
+ >
+ mini_xml_node;
+
+ struct mini_xml
+ {
+ std::string name; // tag name
+ std::vector<mini_xml_node> children; // children
+ };
+}
+
+// We need to tell fusion about our mini_xml struct
+// to make it a first-class fusion citizen
+BOOST_FUSION_ADAPT_STRUCT(
+ client::mini_xml,
+ (std::string, name)
+ (std::vector<client::mini_xml_node>, children)
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Print out the mini xml tree
+ ///////////////////////////////////////////////////////////////////////////
+ int const tabsize = 4;
+
+ void tab(int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ std::cout << ' ';
+ }
+
+ struct mini_xml_printer
+ {
+ mini_xml_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const;
+
+ int indent;
+ };
+
+ struct mini_xml_node_printer : boost::static_visitor<>
+ {
+ mini_xml_node_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const
+ {
+ mini_xml_printer(indent+tabsize)(xml);
+ }
+
+ void operator()(std::string const& text) const
+ {
+ tab(indent+tabsize);
+ std::cout << "text: \"" << text << '"' << std::endl;
+ }
+
+ int indent;
+ };
+
+ void mini_xml_printer::operator()(mini_xml const& xml) const
+ {
+ tab(indent);
+ std::cout << "tag: " << xml.name << std::endl;
+ tab(indent);
+ std::cout << '{' << std::endl;
+
+ BOOST_FOREACH(mini_xml_node const& node, xml.children)
+ {
+ boost::apply_visitor(mini_xml_node_printer(indent), node);
+ }
+
+ tab(indent);
+ std::cout << '}' << std::endl;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML grammar definition
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_xml2_grammar
+ template <typename Iterator>
+ struct mini_xml_grammar
+ : qi::grammar<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type>
+ {
+ mini_xml_grammar()
+ : mini_xml_grammar::base_type(xml)
+ {
+ using qi::lit;
+ using qi::lexeme;
+ using ascii::char_;
+ using ascii::string;
+ using namespace qi::labels;
+
+ text %= lexeme[+(char_ - '<')];
+ node %= xml | text;
+
+ start_tag %=
+ '<'
+ >> !lit('/')
+ >> lexeme[+(char_ - '>')]
+ >> '>'
+ ;
+
+ end_tag =
+ "</"
+ >> lit(_r1)
+ >> '>'
+ ;
+
+ xml %=
+ start_tag[_a = _1]
+ >> *node
+ >> end_tag(_a)
+ ;
+ }
+
+ qi::rule<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type> xml;
+ qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
+ qi::rule<Iterator, std::string(), ascii::space_type> text;
+ qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
+ qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
+ };
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string storage; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(storage));
+
+ typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar;
+ mini_xml_grammar xml; // Our grammar
+ client::mini_xml ast; // Our tree
+
+ using boost::spirit::ascii::space;
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = phrase_parse(iter, end, xml, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ client::mini_xml_printer printer;
+ printer(ast);
+ return 0;
+ }
+ else
+ {
+ std::string::const_iterator some = iter + std::min(30, int(end - iter));
+ std::string context(iter, (some>end)?end:some);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << context << "...\"\n";
+ std::cout << "-------------------------\n";
+ return 1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/mini_xml3.cpp b/src/boost/libs/spirit/example/qi/mini_xml3.cpp
new file mode 100644
index 00000000..d8926c1a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml3.cpp
@@ -0,0 +1,258 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A mini XML-like parser
+//
+// [ JDG March 25, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace fusion = boost::fusion;
+ namespace phoenix = boost::phoenix;
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML tree representation
+ ///////////////////////////////////////////////////////////////////////////
+ struct mini_xml;
+
+ typedef
+ boost::variant<
+ boost::recursive_wrapper<mini_xml>
+ , std::string
+ >
+ mini_xml_node;
+
+ struct mini_xml
+ {
+ std::string name; // tag name
+ std::vector<mini_xml_node> children; // children
+ };
+}
+
+// We need to tell fusion about our mini_xml struct
+// to make it a first-class fusion citizen
+BOOST_FUSION_ADAPT_STRUCT(
+ client::mini_xml,
+ (std::string, name)
+ (std::vector<client::mini_xml_node>, children)
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Print out the mini xml tree
+ ///////////////////////////////////////////////////////////////////////////
+ int const tabsize = 4;
+
+ void tab(int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ std::cout << ' ';
+ }
+
+ struct mini_xml_printer
+ {
+ mini_xml_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const;
+
+ int indent;
+ };
+
+ struct mini_xml_node_printer : boost::static_visitor<>
+ {
+ mini_xml_node_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const
+ {
+ mini_xml_printer(indent+tabsize)(xml);
+ }
+
+ void operator()(std::string const& text) const
+ {
+ tab(indent+tabsize);
+ std::cout << "text: \"" << text << '"' << std::endl;
+ }
+
+ int indent;
+ };
+
+ void mini_xml_printer::operator()(mini_xml const& xml) const
+ {
+ tab(indent);
+ std::cout << "tag: " << xml.name << std::endl;
+ tab(indent);
+ std::cout << '{' << std::endl;
+
+ BOOST_FOREACH(mini_xml_node const& node, xml.children)
+ {
+ boost::apply_visitor(mini_xml_node_printer(indent), node);
+ }
+
+ tab(indent);
+ std::cout << '}' << std::endl;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML grammar definition
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_xml3_grammar
+ template <typename Iterator>
+ struct mini_xml_grammar
+ : qi::grammar<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type>
+ {
+ mini_xml_grammar()
+ : mini_xml_grammar::base_type(xml, "xml")
+ {
+ using qi::lit;
+ using qi::lexeme;
+ using qi::on_error;
+ using qi::fail;
+ using ascii::char_;
+ using ascii::string;
+ using namespace qi::labels;
+
+ using phoenix::construct;
+ using phoenix::val;
+
+ text %= lexeme[+(char_ - '<')];
+ node %= xml | text;
+
+ start_tag %=
+ '<'
+ >> !lit('/')
+ > lexeme[+(char_ - '>')]
+ > '>'
+ ;
+
+ end_tag =
+ "</"
+ > lit(_r1)
+ > '>'
+ ;
+
+ xml %=
+ start_tag[_a = _1]
+ > *node
+ > end_tag(_a)
+ ;
+
+ xml.name("xml");
+ node.name("node");
+ text.name("text");
+ start_tag.name("start_tag");
+ end_tag.name("end_tag");
+
+ on_error<fail>
+ (
+ xml
+ , std::cout
+ << val("Error! Expecting ")
+ << _4 // what failed?
+ << val(" here: \"")
+ << construct<std::string>(_3, _2) // iterators to error-pos, end
+ << val("\"")
+ << std::endl
+ );
+ }
+
+ qi::rule<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type> xml;
+ qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
+ qi::rule<Iterator, std::string(), ascii::space_type> text;
+ qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
+ qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
+ };
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string storage; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(storage));
+
+ typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar;
+ mini_xml_grammar xml; // Our grammar
+ client::mini_xml ast; // Our tree
+
+ using boost::spirit::ascii::space;
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = phrase_parse(iter, end, xml, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ client::mini_xml_printer printer;
+ printer(ast);
+ return 0;
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ return 1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/mini_xml_samples/1.toyxml b/src/boost/libs/spirit/example/qi/mini_xml_samples/1.toyxml
new file mode 100644
index 00000000..54181ed4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml_samples/1.toyxml
@@ -0,0 +1 @@
+<foo></foo> \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/mini_xml_samples/2.toyxml b/src/boost/libs/spirit/example/qi/mini_xml_samples/2.toyxml
new file mode 100644
index 00000000..266e4b1f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml_samples/2.toyxml
@@ -0,0 +1 @@
+<foo><bar></bar></foo> \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/mini_xml_samples/3.toyxml b/src/boost/libs/spirit/example/qi/mini_xml_samples/3.toyxml
new file mode 100644
index 00000000..9d89cf7b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml_samples/3.toyxml
@@ -0,0 +1,5 @@
+<foo>
+ <bar>bar 1</bar>
+ <bar>bar 2</bar>
+ <bar>bar 3</bar>
+</foo> \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/mini_xml_samples/4.toyxml b/src/boost/libs/spirit/example/qi/mini_xml_samples/4.toyxml
new file mode 100644
index 00000000..0f220f1e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml_samples/4.toyxml
@@ -0,0 +1 @@
+<foo><bar></foo></bar> \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/nabialek.cpp b/src/boost/libs/spirit/example/qi/nabialek.cpp
new file mode 100644
index 00000000..4795578c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/nabialek.cpp
@@ -0,0 +1,98 @@
+/*=============================================================================
+ Copyright (c) 2003 Sam Nabialek
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// The Nabialek trick.
+//
+// [ Sam Nabialek; Somewhere, sometime in 2003... ] spirit1
+// [ JDG November 17, 2009 ] spirit2
+// [ JDG January 10, 2010 ] Updated to use rule pointers
+// for efficiency.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our nabialek_trick grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct nabialek_trick : qi::grammar<
+ Iterator, ascii::space_type, qi::locals<qi::rule<Iterator, ascii::space_type>*> >
+ {
+ nabialek_trick() : nabialek_trick::base_type(start)
+ {
+ using ascii::alnum;
+ using qi::lexeme;
+ using qi::lazy;
+ using qi::_a;
+ using qi::_1;
+
+ id = lexeme[*(ascii::alnum | '_')];
+ one = id;
+ two = id >> ',' >> id;
+
+ keyword.add
+ ("one", &one)
+ ("two", &two)
+ ;
+
+ start = *(keyword[_a = _1] >> lazy(*_a));
+ }
+
+ qi::rule<Iterator, ascii::space_type> id, one, two;
+ qi::rule<Iterator, ascii::space_type, qi::locals<qi::rule<Iterator, ascii::space_type>*> > start;
+ qi::symbols<char, qi::rule<Iterator, ascii::space_type>*> keyword;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ using boost::spirit::ascii::space;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::nabialek_trick<iterator_type> nabialek_trick;
+
+ nabialek_trick g; // Our grammar
+
+ std::string str = "one only\none again\ntwo first,second";
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, g, space);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/num_list1.cpp b/src/boost/libs/spirit/example/qi/num_list1.cpp
new file mode 100644
index 00000000..dc2e696d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/num_list1.cpp
@@ -0,0 +1,90 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// No actions.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist1
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using ascii::space;
+
+ bool r = phrase_parse(
+ first, /*< start iterator >*/
+ last, /*< end iterator >*/
+ double_ >> *(',' >> double_), /*< the parser >*/
+ space /*< the skip-parser >*/
+ );
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ if (client::parse_numbers(str.begin(), str.end()))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/num_list2.cpp b/src/boost/libs/spirit/example/qi/num_list2.cpp
new file mode 100644
index 00000000..9fb854e7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/num_list2.cpp
@@ -0,0 +1,109 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// The numbers are inserted in a vector using phoenix.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace phoenix = boost::phoenix;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist2
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using qi::_1;
+ using ascii::space;
+ using phoenix::push_back;
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[push_back(phoenix::ref(v), _1)]
+ >> *(',' >> double_[push_back(phoenix::ref(v), _1)])
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/num_list3.cpp b/src/boost/libs/spirit/example/qi/num_list3.cpp
new file mode 100644
index 00000000..3ba09ffb
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/num_list3.cpp
@@ -0,0 +1,108 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// The numbers are inserted in a vector using phoenix.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace phoenix = boost::phoenix;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist3
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using qi::_1;
+ using ascii::space;
+ using phoenix::push_back;
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[push_back(phoenix::ref(v), _1)] % ','
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/num_list4.cpp b/src/boost/libs/spirit/example/qi/num_list4.cpp
new file mode 100644
index 00000000..552dd8d1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/num_list4.cpp
@@ -0,0 +1,106 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// The numbers are inserted in a vector using phoenix.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist4
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using qi::_1;
+ using ascii::space;
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_ % ','
+ )
+ ,
+ // End grammar
+
+ space, v);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/parse_date.cpp b/src/boost/libs/spirit/example/qi/parse_date.cpp
new file mode 100644
index 00000000..82b5092d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/parse_date.cpp
@@ -0,0 +1,125 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Hartmut Kaiser
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+
+// This example is not meant to be a sophisticated date parser. It's sole
+// purpose is to demonstrate the intrinsic attribute transformation
+// capabilities of a rule.
+//
+// Note how the rule exposes a fusion sequence, but gets passed an instance of
+// a boost::gregorian::date as the attribute. In order to make these types
+// compatible for the rule we define a specialization of the customization
+// point called 'transform_attribute'.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/date_time.hpp>
+
+// define custom transformation
+namespace boost { namespace spirit { namespace traits
+{
+ // This specialization of the customization point transform_attribute
+ // allows to pass a boost::gregorian::date to a rule which is expecting
+ // a fusion sequence consisting out of three integers as its attribute.
+ template<>
+ struct transform_attribute<
+ boost::gregorian::date, fusion::vector<int, int, int>, qi::domain>
+ {
+ typedef fusion::vector<int, int, int> date_parts;
+
+ // The embedded typedef 'type' exposes the attribute as it will be
+ // passed to the right hand side of the rule.
+ typedef date_parts type;
+
+ // The function pre() is called for down-stream conversion of the
+ // attribute supplied to the rule to the attribute expected by the
+ // right hand side.
+ // The supplied attribute might have been pre-initialized by parsers
+ // (i.e. semantic actions) higher up the parser hierarchy (in the
+ // grammar), in which case we would need to properly initialize the
+ // returned value from the argument. In this example this is not
+ // required, so we just create a new instance of a date_parts.
+ static date_parts pre(boost::gregorian::date)
+ {
+ return date_parts();
+ }
+
+ // The function post() is called for up-stream conversion of the
+ // results returned from parsing the right hand side of the rule.
+ // We need to initialize the attribute supplied to the rule (referenced
+ // by the first argument) with the values taken from the parsing
+ // results (referenced by the second argument).
+ static void post(boost::gregorian::date& d, date_parts const& v)
+ {
+ d = boost::gregorian::date(fusion::at_c<0>(v), fusion::at_c<1>(v)
+ , fusion::at_c<2>(v));
+ }
+
+ // The function fail() is called whenever the parsing of the right hand
+ // side of the rule fails. We don't need to do anything here.
+ static void fail(boost::gregorian::date&) {}
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ template <typename Iterator>
+ bool parse_date(Iterator& first, Iterator last, boost::gregorian::date& d)
+ {
+ typedef boost::fusion::vector<int, int, int> date_parts;
+ qi::rule<Iterator, date_parts(), qi::space_type> date =
+ qi::int_ >> '-' >> qi::int_ >> '-' >> qi::int_;
+
+ return phrase_parse(first, last, date, qi::space, d);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA date parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a date of the form : year-month-day\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ boost::gregorian::date d;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = client::parse_date(iter, end, d);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << d << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/porting_guide_classic.cpp b/src/boost/libs/spirit/example/qi/porting_guide_classic.cpp
new file mode 100644
index 00000000..b12f0f22
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/porting_guide_classic.cpp
@@ -0,0 +1,108 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+//[porting_guide_classic_includes
+#include <boost/spirit/include/classic.hpp>
+#include <boost/spirit/include/phoenix1.hpp>
+#include <iostream>
+#include <string>
+//]
+
+//[porting_guide_classic_namespace
+using namespace boost::spirit::classic;
+//]
+
+//[porting_guide_classic_grammar
+struct roman : public grammar<roman>
+{
+ template <typename ScannerT>
+ struct definition
+ {
+ definition(roman const& self)
+ {
+ hundreds.add
+ ("C" , 100)("CC" , 200)("CCC" , 300)("CD" , 400)("D" , 500)
+ ("DC" , 600)("DCC" , 700)("DCCC" , 800)("CM" , 900) ;
+
+ tens.add
+ ("X" , 10)("XX" , 20)("XXX" , 30)("XL" , 40)("L" , 50)
+ ("LX" , 60)("LXX" , 70)("LXXX" , 80)("XC" , 90) ;
+
+ ones.add
+ ("I" , 1)("II" , 2)("III" , 3)("IV" , 4)("V" , 5)
+ ("VI" , 6)("VII" , 7)("VIII" , 8)("IX" , 9) ;
+
+ first = eps_p [phoenix::var(self.r) = phoenix::val(0)]
+ >> ( +ch_p('M') [phoenix::var(self.r) += phoenix::val(1000)]
+ || hundreds [phoenix::var(self.r) += phoenix::_1]
+ || tens [phoenix::var(self.r) += phoenix::_1]
+ || ones [phoenix::var(self.r) += phoenix::_1]
+ ) ;
+ }
+
+ rule<ScannerT> first;
+ symbols<unsigned> hundreds;
+ symbols<unsigned> tens;
+ symbols<unsigned> ones;
+
+ rule<ScannerT> const& start() const { return first; }
+ };
+
+ roman(unsigned& r_) : r(r_) {}
+ unsigned& r;
+};
+//]
+
+int main()
+{
+ {
+ //[porting_guide_classic_parse
+ std::string input("1,1");
+ parse_info<std::string::iterator> pi = parse(input.begin(), input.end(), int_p);
+
+ if (pi.hit)
+ std::cout << "successful match!\n";
+
+ if (pi.full)
+ std::cout << "full match!\n";
+ else
+ std::cout << "stopped at: " << std::string(pi.stop, input.end()) << "\n";
+
+ std::cout << "matched length: " << pi.length << "\n";
+ //]
+ }
+
+ {
+ //[porting_guide_classic_phrase_parse
+ std::string input(" 1, 1");
+ parse_info<std::string::iterator> pi = parse(input.begin(), input.end(), int_p, space_p);
+
+ if (pi.hit)
+ std::cout << "successful match!\n";
+
+ if (pi.full)
+ std::cout << "full match!\n";
+ else
+ std::cout << "stopped at: " << std::string(pi.stop, input.end()) << "\n";
+
+ std::cout << "matched length: " << pi.length << "\n";
+ //]
+ }
+
+ {
+ //[porting_guide_classic_use_grammar
+ std::string input("MMIX"); // MMIX == 2009
+ unsigned value = 0;
+ roman r(value);
+ parse_info<std::string::iterator> pi = parse(input.begin(), input.end(), r);
+ if (pi.hit)
+ std::cout << "successfully matched: " << value << "\n";
+ //]
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/porting_guide_qi.cpp b/src/boost/libs/spirit/example/qi/porting_guide_qi.cpp
new file mode 100644
index 00000000..d1ec0335
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/porting_guide_qi.cpp
@@ -0,0 +1,106 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+//[porting_guide_qi_includes
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <iostream>
+#include <string>
+#include <algorithm>
+//]
+
+//[porting_guide_qi_namespace
+using namespace boost::spirit;
+//]
+
+//[porting_guide_qi_grammar
+template <typename Iterator>
+struct roman : qi::grammar<Iterator, unsigned()>
+{
+ roman() : roman::base_type(first)
+ {
+ hundreds.add
+ ("C" , 100)("CC" , 200)("CCC" , 300)("CD" , 400)("D" , 500)
+ ("DC" , 600)("DCC" , 700)("DCCC" , 800)("CM" , 900) ;
+
+ tens.add
+ ("X" , 10)("XX" , 20)("XXX" , 30)("XL" , 40)("L" , 50)
+ ("LX" , 60)("LXX" , 70)("LXXX" , 80)("XC" , 90) ;
+
+ ones.add
+ ("I" , 1)("II" , 2)("III" , 3)("IV" , 4)("V" , 5)
+ ("VI" , 6)("VII" , 7)("VIII" , 8)("IX" , 9) ;
+
+ // qi::_val refers to the attribute of the rule on the left hand side
+ first = eps [qi::_val = 0]
+ >> ( +lit('M') [qi::_val += 1000]
+ || hundreds [qi::_val += qi::_1]
+ || tens [qi::_val += qi::_1]
+ || ones [qi::_val += qi::_1]
+ ) ;
+ }
+
+ qi::rule<Iterator, unsigned()> first;
+ qi::symbols<char, unsigned> hundreds;
+ qi::symbols<char, unsigned> tens;
+ qi::symbols<char, unsigned> ones;
+};
+//]
+
+int main()
+{
+ {
+ //[porting_guide_qi_parse
+ std::string input("1,1");
+ std::string::iterator it = input.begin();
+ bool result = qi::parse(it, input.end(), qi::int_);
+
+ if (result)
+ std::cout << "successful match!\n";
+
+ if (it == input.end())
+ std::cout << "full match!\n";
+ else
+ std::cout << "stopped at: " << std::string(it, input.end()) << "\n";
+
+ // seldomly needed: use std::distance to calculate the length of the match
+ std::cout << "matched length: " << std::distance(input.begin(), it) << "\n";
+ //]
+ }
+
+ {
+ //[porting_guide_qi_phrase_parse
+ std::string input(" 1, 1");
+ std::string::iterator it = input.begin();
+ bool result = qi::phrase_parse(it, input.end(), qi::int_, ascii::space);
+
+ if (result)
+ std::cout << "successful match!\n";
+
+ if (it == input.end())
+ std::cout << "full match!\n";
+ else
+ std::cout << "stopped at: " << std::string(it, input.end()) << "\n";
+
+ // seldomly needed: use std::distance to calculate the length of the match
+ std::cout << "matched length: " << std::distance(input.begin(), it) << "\n";
+ //]
+ }
+
+ {
+ //[porting_guide_qi_use_grammar
+ std::string input("MMIX"); // MMIX == 2009
+ std::string::iterator it = input.begin();
+ unsigned value = 0;
+ roman<std::string::iterator> r;
+ if (qi::parse(it, input.end(), r, value))
+ std::cout << "successfully matched: " << value << "\n";
+ //]
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/reference.cpp b/src/boost/libs/spirit/example/qi/reference.cpp
new file mode 100644
index 00000000..4cd8a147
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/reference.cpp
@@ -0,0 +1,1481 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ 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)
+=============================================================================*/
+
+// this code is not supposed to be executed, so the asserts are for
+// demonstration purposes only
+// boostinspect:naassert_macro
+
+//[reference_includes
+#include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/assert.hpp>
+#include <boost/predef/other/endian.h>
+#include <iostream>
+#include <string>
+#include <cstdlib>
+//]
+
+//[reference_test
+template <typename P>
+void test_parser(
+ char const* input, P const& p, bool full_match = true)
+{
+ using boost::spirit::qi::parse;
+
+ char const* f(input);
+ char const* l(f + strlen(f));
+ if (parse(f, l, p) && (!full_match || (f == l)))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+
+template <typename P>
+void test_phrase_parser(
+ char const* input, P const& p, bool full_match = true)
+{
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::qi::ascii::space;
+
+ char const* f(input);
+ char const* l(f + strlen(f));
+ if (phrase_parse(f, l, p, space) && (!full_match || (f == l)))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_test_attr
+template <typename P, typename T>
+void test_parser_attr(
+ char const* input, P const& p, T& attr, bool full_match = true)
+{
+ using boost::spirit::qi::parse;
+
+ char const* f(input);
+ char const* l(f + strlen(f));
+ if (parse(f, l, p, attr) && (!full_match || (f == l)))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+
+template <typename P, typename T>
+void test_phrase_parser_attr(
+ char const* input, P const& p, T& attr, bool full_match = true)
+{
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::qi::ascii::space;
+
+ char const* f(input);
+ char const* l(f + strlen(f));
+ if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_print_info
+struct printer
+{
+ typedef boost::spirit::utf8_string string;
+
+ void element(string const& tag, string const& value, int depth) const
+ {
+ for (int i = 0; i < (depth*4); ++i) // indent to depth
+ std::cout << ' ';
+
+ std::cout << "tag: " << tag;
+ if (value != "")
+ std::cout << ", value: " << value;
+ std::cout << std::endl;
+ }
+};
+
+void print_info(boost::spirit::info const& what)
+{
+ using boost::spirit::basic_info_walker;
+
+ printer pr;
+ basic_info_walker<printer> walker(pr, what.tag, 0);
+ boost::apply_visitor(walker, what.value);
+}
+//]
+
+//[reference_test_real_policy
+///////////////////////////////////////////////////////////////////////////////
+// These policies can be used to parse thousand separated
+// numbers with at most 2 decimal digits after the decimal
+// point. e.g. 123,456,789.01
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+struct ts_real_policies : boost::spirit::qi::ureal_policies<T>
+{
+ // 2 decimal places Max
+ template <typename Iterator, typename Attribute>
+ static bool
+ parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr,
+ int& frac_digits)
+ {
+ Iterator savef = first;
+ bool r = boost::spirit::qi::
+ extract_uint<T, 10, 1, 2, true>::call(first, last, attr);
+ if (r) {
+ // Optimization note: don't compute frac_digits if T is
+ // an unused_type. This should be optimized away by the compiler.
+ if (!boost::is_same<T, boost::spirit::unused_type>::value)
+ frac_digits = static_cast<int>(std::distance(savef, first));
+ }
+ return r;
+ }
+
+ // No exponent
+ template <typename Iterator>
+ static bool
+ parse_exp(Iterator&, Iterator const&)
+ {
+ return false;
+ }
+
+ // No exponent
+ template <typename Iterator, typename Attribute>
+ static bool
+ parse_exp_n(Iterator&, Iterator const&, Attribute&)
+ {
+ return false;
+ }
+
+ // Thousands separated numbers
+ template <typename Iterator, typename Accumulator>
+ static bool
+ parse_n(Iterator& first, Iterator const& last, Accumulator& result)
+ {
+ using boost::spirit::qi::uint_parser;
+ namespace qi = boost::spirit::qi;
+
+ uint_parser<unsigned, 10, 1, 3> uint3;
+ uint_parser<unsigned, 10, 3, 3> uint3_3;
+
+ if (parse(first, last, uint3, result))
+ {
+ Accumulator n;
+ Iterator iter = first;
+
+ while (qi::parse(iter, last, ',') && qi::parse(iter, last, uint3_3, n))
+ {
+ result = result * 1000 + n;
+ first = iter;
+ }
+
+ return true;
+ }
+ return false;
+ }
+};
+//]
+
+//[reference_test_bool_policy
+///////////////////////////////////////////////////////////////////////////////
+// These policies can be used to parse "eurt" (i.e. "true" spelled backwards)
+// as `false`
+///////////////////////////////////////////////////////////////////////////////
+struct backwards_bool_policies : boost::spirit::qi::bool_policies<>
+{
+ // we want to interpret a 'true' spelled backwards as 'false'
+ template <typename Iterator, typename Attribute>
+ static bool
+ parse_false(Iterator& first, Iterator const& last, Attribute& attr)
+ {
+ namespace qi = boost::spirit::qi;
+ if (qi::detail::string_parse("eurt", first, last, qi::unused))
+ {
+ namespace traits = boost::spirit::traits;
+ traits::assign_to(false, attr); // result is false
+ return true;
+ }
+ return false;
+ }
+};
+//]
+
+//[reference_qi_complex
+// a simple complex number representation z = a + bi
+struct complex
+{
+ complex (double a = 0.0, double b = 0.0)
+ : a(a), b(b)
+ {}
+
+ double a;
+ double b;
+};
+//]
+
+//[reference_qi_stream_complex
+// define streaming operator for the type complex
+std::istream&
+operator>> (std::istream& is, complex& z)
+{
+ char lbrace = '\0', comma = '\0', rbrace = '\0';
+ is >> lbrace >> z.a >> comma >> z.b >> rbrace;
+ if (lbrace != '{' || comma != ',' || rbrace != '}')
+ is.setstate(std::ios_base::failbit);
+ return is;
+}
+//]
+
+//[reference_qi_auto_complex
+/*`The following construct is required to allow the `complex` data structure
+ to be utilized as a __fusion__ sequence. This is required as we will
+ emit output for this data structure with a __qi__ sequence:
+ `'{' >> qi::double_ >> ',' >> qi::double_ >> '}'`.
+*/
+BOOST_FUSION_ADAPT_STRUCT(
+ complex,
+ (double, a)
+ (double, b)
+)
+
+/*`We add a specialization for the create_parser customization point
+ defining a custom output format for the complex type. Generally, any
+ specialization for create_parser is expected to return the proto
+ expression to be used to match input for the type the customization
+ point has been specialized for.
+ */
+/*`We need to utilize `proto::deep_copy` as the expression contains literals
+ (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto
+ expression by reference only. The deep copy converts the proto tree to
+ hold this by value. The deep copy operation can be left out for simpler
+ proto expressions (not containing references to temporaries). Alternatively
+ you could use the `proto::make_expr` facility to build the required
+ proto expression.
+*/
+namespace boost { namespace spirit { namespace traits
+{
+ template <>
+ struct create_parser<complex>
+ {
+ typedef proto::result_of::deep_copy<
+ BOOST_TYPEOF('{' >> qi::double_ >> ',' >> qi::double_ >> '}')
+ >::type type;
+
+ static type call()
+ {
+ return proto::deep_copy(
+ '{' >> qi::double_ >> ',' >> qi::double_ >> '}');
+ }
+ };
+}}}
+//]
+
+//[reference_qi_auxiliary_attr_cast_data1
+// this is just a test structure we want to use in place of an int
+struct int_data
+{
+ int i;
+};
+
+
+// we provide a custom attribute transformation to allow its use as an int
+namespace boost { namespace spirit { namespace traits
+{
+ // in this case we just expose the embedded 'int' as the attribute instance
+ // to use, allowing to leave the function 'post()' empty
+ template <>
+ struct transform_attribute<int_data, int, qi::domain>
+ {
+ typedef int& type;
+ static int& pre(int_data& d) { return d.i; }
+ static void post(int_data& val, int const& attr) {}
+ static void fail(int_data&) {}
+ };
+}}}
+//]
+
+namespace client
+{
+ using boost::spirit::qi::grammar;
+ using boost::spirit::qi::rule;
+ using boost::spirit::ascii::space_type;
+
+//[reference_grammar_definition
+/*`Basic grammar usage:
+ */
+ struct num_list : grammar<char const*, space_type>
+ {
+ num_list() : base_type(start)
+ {
+ using boost::spirit::int_;
+ num = int_;
+ start = num >> *(',' >> num);
+ }
+
+ rule<char const*, space_type> start, num;
+ };
+//]
+}
+
+int
+main()
+{
+ {
+ //[reference_using_declarations_lit_char
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::char_;
+ //]
+
+ //[reference_char_literals
+ test_parser("x", 'x'); // plain literal
+ test_parser("x", lit('x')); // explicit literal
+ test_parser("x", char_('x')); // ascii::char_
+ //]
+
+ //[reference_char_range
+ char ch;
+ test_parser_attr("5", char_('0','9'), ch); // ascii::char_ range
+ std::cout << ch << std::endl; // prints '5'
+ //]
+
+ //[reference_char_set
+ test_parser_attr("5", char_("0-9"), ch); // ascii::char_ set
+ std::cout << ch << std::endl; // prints '5'
+ //]
+
+ //[reference_char_phoenix
+ namespace phx = boost::phoenix;
+ test_parser("x", phx::val('x')); // direct
+ test_parser("5",
+ char_(phx::val('0'),phx::val('9'))); // ascii::char_ range
+ //]
+ }
+
+ {
+ //[reference_using_declarations_lit_string
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::string;
+ //]
+
+ //[reference_string_literals
+ test_parser("boost", "boost"); // plain literal
+ test_parser("boost", lit("boost")); // explicit literal
+ test_parser("boost", string("boost")); // ascii::string
+ //]
+ }
+
+ {
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::string;
+
+ //[reference_string_std_string
+ std::string s("boost");
+ test_parser("boost", s); // direct
+ test_parser("boost", lit(s)); // explicit
+ test_parser("boost", string(s)); // ascii::string
+ //]
+ }
+
+ {
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::string;
+
+ //[reference_string_phoenix
+ namespace phx = boost::phoenix;
+ test_parser("boost", phx::val("boost")); // direct
+ test_parser("boost", lit(phx::val("boost"))); // explicit
+ test_parser("boost", string(phx::val("boost"))); // ascii::string
+ //]
+ }
+
+ {
+ //[reference_using_declarations_symbols
+ using boost::spirit::qi::symbols;
+ //]
+
+ //[reference_symbols_with_data
+ symbols<char, int> sym;
+
+ sym.add
+ ("Apple", 1)
+ ("Banana", 2)
+ ("Orange", 3)
+ ;
+
+ int i;
+ test_parser_attr("Banana", sym, i);
+ std::cout << i << std::endl;
+ //]
+ }
+
+ {
+ //[reference_using_declarations_lexeme
+ using boost::spirit::qi::lexeme;
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::digit;
+ //]
+
+ //[reference_lexeme
+ /*`The use of lexeme here will prevent skipping in between the
+ digits and the sign making inputs such as `"1 2 345"` erroneous.*/
+ test_phrase_parser("12345", lexeme[ -(lit('+') | '-') >> +digit ]);
+ //]
+ }
+
+ // as
+ {
+ //[reference_using_declarations_as
+ using boost::spirit::utree;
+ using boost::spirit::utree_type;
+ using boost::spirit::utf8_symbol_type;
+ using boost::spirit::qi::as;
+ using boost::spirit::qi::as_string;
+ using boost::spirit::qi::char_;
+ //]
+
+ //[reference_as
+ /*`To properly handle string concatenation with __utree__, we
+ make use of `as_string[]`. We also use `as<T>` to explicitly create
+ a __utree__ symbol node.*/
+ utree ut;
+
+ typedef as<utf8_symbol_type> as_symbol_type;
+ as_symbol_type const as_symbol = as_symbol_type();
+
+ test_parser_attr("foo", as_string[*char_], ut);
+ std::cout << ut << std::endl; // will output >"foo"<
+ BOOST_ASSERT(ut.which() == utree_type::string_type);
+ ut.clear();
+
+ test_parser_attr("foo", as<std::string>()[*char_], ut);
+ std::cout << ut << std::endl; // will output >"foo"<
+ BOOST_ASSERT(ut.which() == utree_type::string_type);
+ ut.clear();
+
+ test_parser_attr("foo", as_symbol[*char_], ut);
+ std::cout << ut << std::endl; // will output >foo<
+ BOOST_ASSERT(ut.which() == utree_type::symbol_type);
+ ut.clear();
+
+ test_parser_attr("foo", as<utf8_symbol_type>()[*char_], ut);
+ std::cout << ut << std::endl; // will output >foo<
+ BOOST_ASSERT(ut.which() == utree_type::symbol_type);
+ //]
+ }
+
+ {
+ //[reference_using_declarations_no_skip
+ using boost::spirit::qi::no_skip;
+ using boost::spirit::qi::char_;
+ //]
+
+ //[reference_no_skip
+ /*`The use of no_skip here will prevent skipping of whitespace in front
+ and in between the characters of the string `' abc '`.*/
+
+ std::string str;
+ test_phrase_parser_attr("' abc '",
+ '\'' >> no_skip[+~char_('\'')] >> '\'', str);
+ std::cout << str << std::endl; // will output: > abc <
+ //]
+ }
+
+ {
+ //[reference_using_declarations_hold
+ using boost::spirit::qi::hold;
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::attr;
+ //]
+
+ //[reference_hold
+ /*`The use of `hold[]` here will make sure the changes to the attribute
+ caused by the (failing) first alternative will not be visible after
+ the whole parsing succeeded. */
+
+ std::vector<int> v;
+ test_phrase_parser_attr("123",
+ hold[int_ >> ':' >> int_] | int_ >> attr(0), v);
+ std::cout << v[0] << "," << v[1] << std::endl; // will output: >123,0<
+ //]
+ }
+
+ {
+ //[reference_using_declarations_no_case
+ using boost::spirit::ascii::no_case;
+ using boost::spirit::ascii::char_;
+ using boost::spirit::ascii::alnum;
+ using boost::spirit::qi::symbols;
+ //]
+
+ //[reference_no_case
+ test_parser("X", no_case[char_('x')]);
+ test_parser("6", no_case[alnum]);
+ //]
+
+ //[reference_symbols_with_no_case
+ symbols<char, int> sym;
+
+ sym.add
+ ("apple", 1) // symbol strings are added in lowercase...
+ ("banana", 2)
+ ("orange", 3)
+ ;
+
+ int i;
+ // ...because sym is used for case-insensitive parsing
+ test_parser_attr("Apple", no_case[ sym ], i);
+ std::cout << i << std::endl;
+ test_parser_attr("ORANGE", no_case[ sym ], i);
+ std::cout << i << std::endl;
+ //]
+ }
+
+ {
+ //[reference_using_declarations_omit
+ using boost::spirit::qi::omit;
+ using boost::spirit::qi::int_;
+ using boost::spirit::ascii::char_;
+ //]
+
+ //[reference_omit
+ /*`This parser ignores the first two characters
+ and extracts the succeeding `int`:*/
+ int i;
+ test_parser_attr("xx345", omit[char_ >> char_] >> int_, i);
+ std::cout << i << std::endl; // should print 345
+ //]
+ }
+
+ {
+ //[reference_using_declarations_matches
+ using boost::spirit::qi::matches;
+ using boost::spirit::qi::int_;
+ //]
+
+ //[reference_matches
+ /*`This parser tries to match an `int` and returns `true` a its
+ attribute as it succeeded matching: */
+ bool result = false;
+ test_parser_attr("345", matches[int_], result);
+ std::cout << std::boolalpha << result << std::endl; // should print: true
+
+ /*`This parser tries to match an `int` as well and returns `false` as
+ its attribute as it fails matching: */
+ result = true;
+ test_parser_attr("abc", matches[int_], result);
+ std::cout << std::boolalpha << result << std::endl; // should print: false
+ //]
+ }
+
+ {
+ //[reference_using_declarations_raw
+ using boost::spirit::qi::raw;
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::ascii::alnum;
+ //]
+
+ //[reference_raw
+ //`This parser matches and extracts C++ identifiers:
+ std::string id;
+ test_parser_attr("James007", raw[(alpha | '_') >> *(alnum | '_')], id);
+ std::cout << id << std::endl; // should print James007
+ //]
+ }
+
+ {
+ //[reference_using_declarations_repeat
+ using boost::spirit::qi::repeat;
+ using boost::spirit::qi::lit;
+ using boost::spirit::qi::uint_parser;
+ using boost::spirit::qi::_1;
+ using boost::spirit::ascii::char_;
+ namespace phx = boost::phoenix;
+ //]
+
+ //[reference_repeat
+ //`A parser for a file name with a maximum of 255 characters:
+ test_parser("batman.jpeg", repeat(1, 255)[char_("a-zA-Z_./")]);
+
+ /*`A parser for a specific bitmap file format which has exactly 4096 RGB color information.
+ (for the purpose of this example, we will be testing only 3 RGB color information.)
+ */
+ uint_parser<unsigned, 16, 6, 6> rgb;
+ std::vector<unsigned> colors;
+ test_parser_attr("ffffff0000003f3f3f", repeat(3)[rgb], colors);
+ std::cout
+ << std::hex
+ << colors[0] << ','
+ << colors[1] << ','
+ << colors[2] << std::endl;
+
+ /*`A 256 bit binary string (1..256 1s or 0s). (For the purpose of this example,
+ we will be testing only 16 bits.)
+ */
+ test_parser("1011101011110010", repeat(16)[lit('1') | '0']);
+ //]
+
+ std::cout << std::dec; // reset to decimal
+
+ //[reference_repeat_pascal
+ /*`This trivial example cannot be practically defined in traditional EBNF.
+ Although some EBNF variants allow more powerful repetition constructs other
+ than the Kleene Star, we are still limited to parsing fixed strings.
+ The nature of EBNF forces the repetition factor to be a constant.
+ On the other hand, Spirit allows the repetition factor to be variable at
+ run time. We could write a grammar that accepts the input string above.
+ Example using phoenix:
+ */
+ std::string str;
+ int n;
+ test_parser_attr("\x0bHello World",
+ char_[phx::ref(n) = _1] >> repeat(phx::ref(n))[char_], str);
+ std::cout << n << ',' << str << std::endl; // will print "11,Hello World"
+ //]
+ }
+
+ {
+ //[reference_using_declarations_skip
+ using boost::spirit::qi::skip;
+ using boost::spirit::qi::int_;
+ using boost::spirit::ascii::space;
+ //]
+
+ //[reference_skip
+ /*`Explicitly specify a skip parser. This parser parses comma
+ delimited numbers, ignoring spaces.*/
+ test_parser("1, 2, 3, 4, 5", skip(space)[int_ >> *(',' >> int_)]);
+ //]
+ }
+
+ // attr()
+ {
+ //[reference_using_declarations_attr
+ namespace phx = boost::phoenix;
+ using boost::spirit::qi::attr;
+ //]
+
+ //[reference_attr
+ std::string str;
+ test_parser_attr("", attr("boost"), str);
+ std::cout << str << std::endl; // will print 'boost'
+
+ double d;
+ test_parser_attr("", attr(1.0), d);
+ std::cout << d << std::endl; // will print '1.0'
+ //]
+
+ //[reference_attr_phoenix
+ d = 0.0;
+ double d1 = 1.2;
+ test_parser_attr("", attr(phx::ref(d1)), d);
+ std::cout << d << std::endl; // will print '1.2'
+ //]
+ }
+
+ // attr_cast
+ {
+ //[reference_qi_using_declarations_attr_cast
+ using boost::spirit::qi::int_;
+ //]
+
+ //[reference_qi_attr_cast1
+ int_data d = { 0 };
+ test_parser_attr("1", boost::spirit::qi::attr_cast(int_), d);
+ std::cout << d.i << std::endl;
+ //]
+ }
+
+ // eol
+ {
+ //[reference_using_declarations_eol
+ using boost::spirit::qi::eol;
+ //]
+
+ //[reference_eol
+ test_parser("\n", eol);
+ //]
+ }
+
+ // eoi
+ {
+ //[reference_using_declarations_eoi
+ using boost::spirit::qi::eoi;
+ //]
+
+ //[reference_eoi
+ test_parser("", eoi);
+ //]
+ }
+
+ // eps
+ {
+ //[reference_using_declarations_eps
+ using boost::spirit::qi::eps;
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::_1;
+ namespace phx = boost::phoenix;
+ //]
+
+ //[reference_eps
+ //`Basic `eps`:
+ test_parser("", eps); // always matches
+ //]
+
+ //[reference_eps_if
+ /*`This example simulates the "classic" `if_p` parser. Here, `int_` will be
+ tried only if the condition, `c`, is true.
+ */
+ bool c = true; // a flag
+ test_parser("1234", eps(phx::ref(c) == true) >> int_);
+ //]
+
+ //[reference_eps_while
+ /*`This example simulates the "classic" `while_p` parser. Here, the kleene loop
+ will exit once the condition, `c`, becomes true. Notice that the condition, `c`,
+ is turned to `false` when we get to parse `4`.
+ */
+ test_phrase_parser("1 2 3 4",
+ *(eps(phx::ref(c) == true) >> int_[phx::ref(c) = (_1 == 4)]));
+ //]
+ }
+
+ // lazy
+ {
+ //[reference_using_declarations_lazy
+ using boost::spirit::qi::lazy;
+ using boost::spirit::ascii::string;
+ using boost::phoenix::val;
+ //]
+
+ //[reference_lazy
+ /*` Here, the phoenix::val expression creates a function
+ that returns its argument when invoked. The lazy expression
+ defers the invocation of this function at parse time. Then,
+ this parser (string parser) is called into action. All this
+ takes place at parse time.
+ */
+ test_parser("Hello", lazy(val(string("Hello"))));
+
+ //` The above is equivalent to:
+ test_parser("Hello", string("Hello"));
+ //]
+ }
+
+ // char class
+ {
+ //[reference_using_declarations_char_class
+ using boost::spirit::ascii::alnum;
+ using boost::spirit::ascii::blank;
+ using boost::spirit::ascii::digit;
+ using boost::spirit::ascii::lower;
+ //]
+
+ //[reference_char_class
+ test_parser("1", alnum);
+ test_parser(" ", blank);
+ test_parser("1", digit);
+ test_parser("a", lower);
+ //]
+ }
+
+ // uint
+ {
+ //[reference_using_declarations_uint
+ using boost::phoenix::val;
+ using boost::spirit::qi::lit;
+ using boost::spirit::qi::uint_;
+ using boost::spirit::qi::uint_parser;
+ //]
+
+ //[reference_uint
+ // unsigned int
+ test_parser("12345", uint_);
+ test_parser("12345", uint_(12345));
+ test_parser("12345", uint_(val(12345)));
+
+ // literals
+ test_parser("12345", lit(12345));
+ test_parser("12345", lit(val(12345)));
+ //]
+
+ //[reference_thousand_separated
+ //`Thousand separated number parser:
+ uint_parser<unsigned, 10, 1, 3> uint3_p; // 1..3 digits
+ uint_parser<unsigned, 10, 3, 3> uint3_3_p; // exactly 3 digits
+ test_parser("12,345,678", uint3_p >> *(',' >> uint3_3_p));
+ //]
+ }
+
+ // int
+ {
+ //[reference_using_declarations_int
+ using boost::phoenix::val;
+ using boost::spirit::qi::lit;
+ using boost::spirit::qi::int_;
+ //]
+
+ //[reference_int
+ // signed int
+ test_parser("+12345", int_);
+ test_parser("-12345", int_);
+ test_parser("+12345", int_(12345));
+ test_parser("-12345", int_(-12345));
+ test_parser("+12345", int_(val(12345)));
+ test_parser("-12345", int_(val(-12345)));
+
+ // literals
+ test_parser("+12345", lit(12345));
+ test_parser("-12345", lit(-12345));
+ test_parser("+12345", lit(val(12345)));
+ test_parser("-12345", lit(val(-12345)));
+ //]
+ }
+
+ // real
+ {
+ //[reference_using_declarations_real
+ using boost::phoenix::val;
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::real_parser;
+ using boost::spirit::qi::lit;
+ //]
+
+ //[reference_real
+ // double
+ test_parser("+12345e6", double_);
+ test_parser("-12345e6", double_);
+ test_parser("+12345e6", double_(12345e6));
+ test_parser("-12345e6", double_(-123456e6));
+ test_parser("+12345e6", double_(val(12345e6)));
+ test_parser("-12345e6", double_(val(-123456e6)));
+
+ // literals
+ test_parser("+12345e6", lit(12345e6));
+ test_parser("-12345e6", lit(-123456e6));
+ test_parser("+12345e6", lit(val(12345e6)));
+ test_parser("-12345e6", lit(val(-123456e6)));
+ //]
+
+ //[reference_custom_real
+ real_parser<double, ts_real_policies<double> > ts_real;
+ test_parser("123,456,789.01", ts_real);
+ test_parser("123,456,789.01", ts_real(123456789.01));
+ //]
+ }
+
+ // bool_
+ {
+ //[reference_using_declarations_bool
+ using boost::phoenix::val;
+ using boost::spirit::qi::bool_;
+ using boost::spirit::qi::bool_parser;
+ using boost::spirit::qi::lit;
+ //]
+
+ //[reference_bool
+ // bool
+ test_parser("true", bool_);
+ test_parser("false", bool_);
+ test_parser("true", bool_(true));
+ test_parser("false", bool_(false));
+ test_parser("true", bool_(val(true)));
+ test_parser("false", bool_(val(false)));
+
+ // literals
+ test_parser("true", lit(true));
+ test_parser("false", lit(false));
+ test_parser("true", lit(val(true)));
+ test_parser("false", lit(val(false)));
+ //]
+
+ //[reference_custom_bool
+ bool_parser<bool, backwards_bool_policies> backwards_bool;
+ test_parser("true", backwards_bool);
+ test_parser("eurt", backwards_bool);
+ test_parser("true", backwards_bool(true));
+ test_parser("eurt", backwards_bool(false));
+ //]
+ }
+
+ // sequence
+ {
+ //[reference_using_declarations_sequence
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::_2;
+ namespace bf = boost::fusion;
+ //]
+
+ //[reference_sequence
+ //`Simple usage:
+ test_parser("xy", char_ >> char_);
+
+ //`Extracting the attribute tuple (using __fusion__):
+ bf::vector<char, char> attr;
+ test_parser_attr("xy", char_ >> char_, attr);
+ std::cout << bf::at_c<0>(attr) << ',' << bf::at_c<1>(attr) << std::endl;
+
+ //`Extracting the attribute vector (using __stl__):
+ std::vector<char> vec;
+ test_parser_attr("xy", char_ >> char_, vec);
+ std::cout << vec[0] << ',' << vec[1] << std::endl;
+
+ //`Extracting the attributes using __qi_semantic_actions__ (using __phoenix__):
+ test_parser("xy", (char_ >> char_)[std::cout << _1 << ',' << _2 << std::endl]);
+ //]
+ }
+
+ // sequential_or
+ {
+ //[reference_using_declarations_sequential_or
+ using boost::spirit::qi::int_;
+ //]
+
+ //[reference_sequential_or
+ //`Correctly parsing a number with optional fractional digits:
+ test_parser("123.456", int_ || ('.' >> int_)); // full
+ test_parser("123", int_ || ('.' >> int_)); // just the whole number
+ test_parser(".456", int_ || ('.' >> int_)); // just the fraction
+
+ /*`A naive but incorrect solution would try to do this using optionals (e.g.):
+
+ int_ >> -('.' >> int_) // will not match ".456"
+ -int_ >> ('.' >> int_) // will not match "123"
+ -int_ >> -('.' >> int_) // will match empty strings! Ooops.
+ */
+ //]
+ }
+
+ // alternative
+ {
+ //[reference_using_declarations_alternative
+ using boost::spirit::ascii::string;
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::_1;
+ using boost::variant;
+ //]
+
+ //[reference_alternative
+ //`Simple usage:
+ test_parser("Hello", string("Hello") | int_);
+ test_parser("123", string("Hello") | int_);
+
+ //`Extracting the attribute variant (using __boost_variant__):
+ variant<std::string, int> attr;
+ test_parser_attr("Hello", string("Hello") | int_, attr);
+
+ /*`This should print `"Hello"`. Note: There are better ways to extract the value
+ from the variant. See __boost_variant__ visitation. This code is solely
+ for demonstration.
+ */
+ if (boost::get<int>(&attr))
+ std::cout << boost::get<int>(attr) << std::endl;
+ else
+ std::cout << boost::get<std::string>(attr) << std::endl;
+
+ /*`Extracting the attributes using __qi_semantic_actions__ with __phoenix__
+ (this should print `123`):
+ */
+ test_parser("123", (string("Hello") | int_)[std::cout << _1 << std::endl]);
+ //]
+
+ }
+
+ // permutation
+ {
+ //[reference_using_declarations_permutation
+ using boost::spirit::ascii::char_;
+ //]
+
+ //[reference_permutation
+ //`Parse a string containing DNA codes (ACTG)
+ test_parser("ACTGGCTAGACT", *(char_('A') ^ 'C' ^ 'T' ^ 'G'));
+ //]
+ }
+
+ // expect
+ {
+ //[reference_using_declarations_expect
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::expectation_failure;
+ //]
+
+ //[reference_expect
+ /*`The code below uses an expectation operator to throw an __qi_expectation_failure__
+ with a deliberate parsing error when `"o"` is expected and `"i"` is what is
+ found in the input. The `catch` block prints the information related to the
+ error. Note: This is low level code that demonstrates the /bare-metal/. Typically,
+ you use an __qi_error_handler__ to deal with the error.
+ */
+ try
+ {
+ test_parser("xi", char_('x') > char_('o')); // should throw an exception
+ }
+ catch (expectation_failure<char const*> const& x)
+ {
+ std::cout << "expected: "; print_info(x.what_);
+ std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
+ }
+ /*`The code above will print:[teletype]
+
+ expected: tag: literal-char, value: o
+ got: "i"``[c++]``
+ */
+ //]
+ }
+
+ // expectd
+ {
+ //[reference_using_declarations_expectd
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::expect;
+ using boost::spirit::qi::expectation_failure;
+ //]
+
+ //[reference_expectd
+ /*`The code below uses an expectation operator to throw an __qi_expectation_failure__
+ with a deliberate parsing error when `"o"` is expected and `"x"` is what is
+ found in the input. The `catch` block prints the information related to the
+ error. Note: This is low level code that demonstrates the /bare-metal/. Typically,
+ you use an __qi_error_handler__ to deal with the error.
+ */
+ try
+ {
+ test_parser("xi", expect[char_('o')]); // should throw an exception
+ }
+ catch (expectation_failure<char const*> const& x)
+ {
+ std::cout << "expected: "; print_info(x.what_);
+ std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
+ }
+ /*`The code above will print:[teletype]
+
+ expected: tag: literal-char, value: o
+ got: "x"``[c++]``
+ */
+ //]
+ }
+
+ // and-predicate
+ {
+ //[reference_and_predicate
+ //`Some using declarations:
+ using boost::spirit::lit;
+
+ /*`Basic look-ahead example: make sure that the last character is a
+ semicolon, but don't consume it, just peek at the next character:
+ */
+ test_phrase_parser("Hello ;", lit("Hello") >> &lit(';'), false);
+ //]
+ }
+
+ // not-predicate
+ {
+ //[reference_not_predicate
+ //`Some using declarations:
+ using boost::spirit::ascii::char_;
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::qi::lit;
+ using boost::spirit::qi::symbols;
+
+ /*`Here's an alternative to the `*(r - x) >> x` idiom using the
+ not-predicate instead. This parses a list of characters terminated
+ by a ';':
+ */
+ test_parser("abcdef;", *(!lit(';') >> char_) >> ';');
+
+ /*`The following parser ensures that we match distinct keywords
+ (stored in a symbol table). To do this, we make sure that the
+ keyword does not follow an alpha or an underscore:
+ */
+ symbols<char, int> keywords;
+ keywords = "begin", "end", "for";
+
+ // This should fail:
+ test_parser("beginner", keywords >> !(alpha | '_'));
+
+ // This is ok:
+ test_parser("end ", keywords >> !(alpha | '_'), false);
+
+ // This is ok:
+ test_parser("for()", keywords >> !(alpha | '_'), false);
+ //]
+ }
+
+ // difference
+ {
+ //[reference_difference
+ //`Some using declarations:
+ using boost::spirit::ascii::char_;
+
+ /*`Parse a C/C++ style comment:
+ */
+ test_parser("/*A Comment*/", "/*" >> *(char_ - "*/") >> "*/");
+ //]
+ }
+
+ // kleene
+ {
+ //[reference_kleene
+ //`Some using declarations:
+ using boost::spirit::qi::int_;
+
+ /*`Parse a comma separated list of numbers and put them in a vector:
+ */
+ std::vector<int> attr;
+ test_phrase_parser_attr(
+ "111, 222, 333, 444, 555", int_ >> *(',' >> int_), attr);
+ std::cout
+ << attr[0] << ',' << attr[1] << ',' << attr[2] << ','
+ << attr[3] << ',' << attr[4]
+ << std::endl;
+ //]
+ }
+
+ // plus
+ {
+ //[reference_plus
+ //`Some using declarations:
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::qi::lexeme;
+
+ /*`Parse one or more strings containing one or more alphabetic
+ characters and put them in a vector:
+ */
+ std::vector<std::string> attr;
+ test_phrase_parser_attr("yaba daba doo", +lexeme[+alpha], attr);
+ std::cout << attr[0] << ',' << attr[1] << ',' << attr[2] << std::endl;
+ //]
+ }
+
+ // optional
+ {
+ //[reference_optional
+ //`Some using declarations:
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::lexeme;
+ using boost::spirit::qi::int_;
+ using boost::fusion::vector;
+ using boost::fusion::at_c;
+ using boost::optional;
+
+ /*`Parse a person info with name (in quotes) optional age [footnote
+ James Bond is shy about his age :-)] and optional sex, all
+ separated by comma.
+ */
+ vector<std::string, optional<int>, optional<char> > attr;
+
+ test_phrase_parser_attr(
+ "\"James Bond\", M"
+ , lexeme['"' >> +(char_ - '"') >> '"'] // name
+ >> -(',' >> int_) // optional age
+ >> -(',' >> char_) // optional sex
+ , attr);
+
+ // Should print: James Bond,M
+ std::cout << at_c<0>(attr); // print name
+ if (at_c<1>(attr)) // print optional age
+ std::cout << ',' << *at_c<1>(attr);
+ if (at_c<2>(attr)) // print optional sex
+ std::cout << ',' << *at_c<2>(attr);
+ std::cout << std::endl;
+ //]
+ }
+
+ // list
+ {
+ //[reference_list
+ //`Some using declarations:
+ using boost::spirit::qi::int_;
+
+ /*`Parse a comma separated list of numbers and put them in a vector:
+ */
+ std::vector<int> attr;
+ test_phrase_parser_attr(
+ "111, 222, 333, 444, 555", int_ % ',', attr);
+ std::cout
+ << attr[0] << ',' << attr[1] << ',' << attr[2] << ','
+ << attr[3] << ',' << attr[4]
+ << std::endl;
+ //]
+ }
+
+ // stream
+ {
+ //[reference_qi_stream
+ //`Using declarations and variables:
+ using boost::spirit::qi::stream;
+ using boost::spirit::qi::stream_parser;
+
+ /*`Parse a simple string using the operator>>(istream&, std::string&);
+ */
+ std::string str;
+ test_parser_attr("abc", stream, str);
+ std::cout << str << std::endl; // prints: abc
+
+ /*`Parse our complex type using the operator>>(istream&, complex&);
+ */
+ complex c;
+ test_parser_attr("{1.0,2.5}", stream_parser<char, complex>(), c);
+ std::cout << c.a << "," << c.b << std::endl; // prints: 1.0,2.5
+ //]
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // auto module
+ {
+ //[reference_qi_using_declarations_auto
+ using boost::spirit::qi::auto_;
+ //]
+
+ //[reference_qi_auto
+ /*`Parse a simple integer using the generated parser component `int_`:
+ */
+ int i = 0;
+ test_parser_attr("123", auto_, i);
+ std::cout << i << std::endl; // prints: 123
+
+ /*`Parse an instance of the `complex` data type as defined above using
+ the parser as generated by the defined customization point:
+ */
+ complex c;
+ test_parser_attr("{1.2,2.4}", auto_, c);
+ std::cout << c.a << "," << c.b << std::endl; // prints: 1.2,2.4
+ //]
+ }
+
+ // native binary
+ {
+ //[reference_qi_native_binary
+ //`Using declarations and variables:
+ using boost::spirit::qi::byte_;
+ using boost::spirit::qi::word;
+ using boost::spirit::qi::dword;
+ using boost::spirit::qi::qword;
+
+ boost::uint8_t uc;
+ boost::uint16_t us;
+ boost::uint32_t ui;
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ boost::uint64_t ul;
+//<-
+#endif
+
+#if BOOST_ENDIAN_LITTLE_BYTE
+//->
+ //`Basic usage of the native binary parsers for little endian platforms:
+ test_parser_attr("\x01", byte_, uc); assert(uc == 0x01);
+ test_parser_attr("\x01\x02", word, us); assert(us == 0x0201);
+ test_parser_attr("\x01\x02\x03\x04", dword, ui); assert(ui == 0x04030201);
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul);
+ assert(ul == 0x0807060504030201LL);
+
+//<-
+#endif
+//->
+ test_parser("\x01", byte_(0x01));
+ test_parser("\x01\x02", word(0x0201));
+ test_parser("\x01\x02\x03\x04", dword(0x04030201));
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
+ qword(0x0807060504030201LL));
+//<-
+#endif
+#else
+//->
+ //`Basic usage of the native binary parsers for big endian platforms:
+ test_parser_attr("\x01", byte_, uc); assert(uc == 0x01);
+ test_parser_attr("\x01\x02", word, us); assert(us == 0x0102);
+ test_parser_attr("\x01\x02\x03\x04", dword, ui); assert(ui == 0x01020304);
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul);
+ assert(0x0102030405060708LL);
+
+//<-
+#endif
+//->
+ test_parser("\x01", byte_(0x01));
+ test_parser("\x01\x02", word(0x0102));
+ test_parser("\x01\x02\x03\x04", dword(0x01020304));
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
+ qword(0x0102030405060708LL));
+//<-
+#endif
+#endif
+//->
+ //]
+ }
+
+ // little binary
+ {
+ //[reference_qi_little_binary
+ //`Using declarations and variables:
+ using boost::spirit::qi::little_word;
+ using boost::spirit::qi::little_dword;
+ using boost::spirit::qi::little_qword;
+
+ boost::uint16_t us;
+ boost::uint32_t ui;
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ boost::uint64_t ul;
+//<-
+#endif
+
+//->
+ //`Basic usage of the little endian binary parsers:
+ test_parser_attr("\x01\x02", little_word, us); assert(us == 0x0201);
+ test_parser_attr("\x01\x02\x03\x04", little_dword, ui); assert(ui == 0x04030201);
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", little_qword, ul);
+ assert(ul == 0x0807060504030201LL);
+
+//<-
+#endif
+//->
+ test_parser("\x01\x02", little_word(0x0201));
+ test_parser("\x01\x02\x03\x04", little_dword(0x04030201));
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
+ little_qword(0x0807060504030201LL));
+//<-
+#endif
+//->
+ //]
+ }
+
+ // big binary
+ {
+ //[reference_qi_big_binary
+ //`Using declarations and variables:
+ using boost::spirit::qi::big_word;
+ using boost::spirit::qi::big_dword;
+ using boost::spirit::qi::big_qword;
+
+ boost::uint16_t us;
+ boost::uint32_t ui;
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ boost::uint64_t ul;
+//<-
+#endif
+
+//->
+ //`Basic usage of the big endian binary parsers:
+ test_parser_attr("\x01\x02", big_word, us); assert(us == 0x0102);
+ test_parser_attr("\x01\x02\x03\x04", big_dword, ui); assert(ui == 0x01020304);
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", big_qword, ul);
+ assert(0x0102030405060708LL);
+
+//<-
+#endif
+//->
+ test_parser("\x01\x02", big_word(0x0102));
+ test_parser("\x01\x02\x03\x04", big_dword(0x01020304));
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
+ big_qword(0x0102030405060708LL));
+//<-
+#endif
+//->
+ //]
+ }
+
+ // rule
+ {
+ //[reference_rule
+ //`Some using declarations:
+ using boost::spirit::qi::rule;
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::locals;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::_a;
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::ascii::char_;
+ using boost::spirit::ascii::space_type;
+
+ /*`Basic rule:
+ */
+ rule<char const*> r;
+ r = int_;
+ test_parser("123", r);
+
+ /*`Rule with synthesized attribute:
+ */
+ rule<char const*, int()> ra;
+ ra = int_;
+ int i;
+ test_parser_attr("123", ra, i);
+ assert(i == 123);
+
+ /*`Rule with skipper and synthesized attribute:
+ */
+ rule<char const*, std::vector<int>(), space_type> rs;
+ rs = *int_;
+ std::vector<int> v;
+ test_phrase_parser_attr("123 456 789", rs, v);
+ assert(v[0] == 123);
+ assert(v[1] == 456);
+ assert(v[2] == 789);
+
+ /*`Rule with one local variable:
+ */
+ rule<char const*, locals<char> > rl;
+ rl = alpha[_a = _1] >> char_(_a); // get two identical characters
+ test_parser("aa", rl); // pass
+ test_parser("ax", rl); // fail
+ //]
+ }
+
+ // grammar
+ {
+ using client::num_list;
+
+ //[reference_grammar_using
+ //`Some using declarations:
+ using boost::spirit::ascii::space_type;
+ using boost::spirit::int_;
+ using boost::spirit::qi::grammar;
+ using boost::spirit::qi::rule;
+ //]
+
+ //[reference_grammar
+ //`How to use the example grammar:
+ num_list nlist;
+ test_phrase_parser("123, 456, 789", nlist);
+ //]
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/reorder_struct.cpp b/src/boost/libs/spirit/example/qi/reorder_struct.cpp
new file mode 100644
index 00000000..5f5a50b1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/reorder_struct.cpp
@@ -0,0 +1,130 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The main purpose of this example is to show how a single fusion sequence
+// can be filled from a parsed input of the elements in different sequences
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/mpl/print.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/struct.hpp>
+#include <boost/fusion/include/nview.hpp>
+#include <boost/foreach.hpp>
+
+namespace fusion = boost::fusion;
+namespace qi = boost::spirit::qi;
+
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ // Our employee struct
+ struct employee
+ {
+ std::string surname;
+ std::string forename;
+ int age;
+ double salary;
+ std::string department;
+ };
+
+ // define iterator type
+ typedef std::string::const_iterator iterator_type;
+
+ // This is the output routine taking a format description and the data to
+ // print
+ template <typename Parser, typename Sequence>
+ bool parse(std::string const& input, Parser const& p, Sequence& s)
+ {
+ iterator_type begin = input.begin();
+ return qi::parse(begin, input.end(), p, s);
+ }
+}
+
+// We need to tell fusion about our employee struct to make it a first-class
+// fusion citizen. This has to be in global scope. Note that we don't need to
+// list the members of our struct in the same sequence a they are defined
+BOOST_FUSION_ADAPT_STRUCT(
+ client::employee,
+ (int, age)
+ (std::string, surname)
+ (std::string, forename)
+ (std::string, department)
+ (double, salary)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// that's the different types we need to reorder the attributes
+typedef fusion::result_of::as_nview<client::employee, 2, 0>::type name_and_age;
+typedef fusion::result_of::as_nview<client::employee, 1, 2, 4>::type names_and_salary;
+typedef fusion::result_of::as_nview<client::employee, 2, 0, 3>::type name_age_and_department;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::string str;
+
+ // some employees
+ client::employee john;
+ client::employee mary;
+ client::employee tom;
+
+ // print data about employees in different formats
+ {
+ // parse forename and age only
+ name_and_age johnview(fusion::as_nview<2, 0>(john));
+ bool r = client::parse(
+ "John, 25",
+ *(qi::char_ - ',') >> ", " >> qi::int_,
+ johnview);
+ if (r) {
+ std::cout << "Parsed: " << john.forename << ", " << john.age
+ << std::endl;
+ }
+
+ // parse surname, forename, and salary
+ names_and_salary maryview(fusion::as_nview<1, 2, 4>(mary));
+ r = client::parse(
+ "Higgins, Mary: 2200.36",
+ *(qi::char_ - ',') >> ", " >> *(qi::char_ - ':') >> ": " >> qi::double_,
+ maryview);
+ if (r) {
+ std::cout << "Parsed: " << mary.forename << ", " << mary.surname
+ << ", " << mary.salary << std::endl;
+ }
+
+ // parse forename, age, and department
+ name_age_and_department tomview(fusion::as_nview<2, 0, 3>(tom));
+ client::parse(
+ "Tom: 48 (Boss)",
+ *(qi::char_ - ':') >> ": " >> qi::int_ >> " (" >> *(qi::char_ - ')') >> ')',
+ tomview);
+ if (r) {
+ std::cout << "Parsed: " << tom.forename << ", " << tom.age
+ << ", " << tom.department << std::endl;
+ }
+ }
+
+ // now parse a list of several employees and print them all
+ std::vector<client::employee> employees;
+
+ // parse surname, forename, and salary for all employees
+ {
+ qi::rule<client::iterator_type, names_and_salary()> r =
+ *(qi::char_ - ',') >> ", " >> *(qi::char_ - ',') >> ", " >> qi::double_;
+
+ bool result = client::parse(
+ "John, Smith, 2000.50\n" "Mary, Higgins, 2200.36\n" "Tom, Taylor, 3200.00\n",
+ r % qi::eol, employees);
+
+ std::cout << "Parsed: " << std::endl;
+ BOOST_FOREACH(client::employee const& e, employees)
+ {
+ std::cout << e.forename << ", " << e.surname << ", " << e.salary
+ << std::endl;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/roman.cpp b/src/boost/libs/spirit/example/qi/roman.cpp
new file mode 100644
index 00000000..e98c2a8a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/roman.cpp
@@ -0,0 +1,188 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Roman Numerals Parser (demonstrating the symbol table). This is
+// discussed in the "Symbols" chapter in the Spirit User's Guide.
+//
+// [ JDG August 22, 2002 ] spirit1
+// [ JDG March 13, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Parse roman hundreds (100..900) numerals using the symbol table.
+ // Notice that the data associated with each slot is the parser's attribute
+ // (which is passed to attached semantic actions).
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_roman_hundreds
+ struct hundreds_ : qi::symbols<char, unsigned>
+ {
+ hundreds_()
+ {
+ add
+ ("C" , 100)
+ ("CC" , 200)
+ ("CCC" , 300)
+ ("CD" , 400)
+ ("D" , 500)
+ ("DC" , 600)
+ ("DCC" , 700)
+ ("DCCC" , 800)
+ ("CM" , 900)
+ ;
+ }
+
+ } hundreds;
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Parse roman tens (10..90) numerals using the symbol table.
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_roman_tens
+ struct tens_ : qi::symbols<char, unsigned>
+ {
+ tens_()
+ {
+ add
+ ("X" , 10)
+ ("XX" , 20)
+ ("XXX" , 30)
+ ("XL" , 40)
+ ("L" , 50)
+ ("LX" , 60)
+ ("LXX" , 70)
+ ("LXXX" , 80)
+ ("XC" , 90)
+ ;
+ }
+
+ } tens;
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Parse roman ones (1..9) numerals using the symbol table.
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_roman_ones
+ struct ones_ : qi::symbols<char, unsigned>
+ {
+ ones_()
+ {
+ add
+ ("I" , 1)
+ ("II" , 2)
+ ("III" , 3)
+ ("IV" , 4)
+ ("V" , 5)
+ ("VI" , 6)
+ ("VII" , 7)
+ ("VIII" , 8)
+ ("IX" , 9)
+ ;
+ }
+
+ } ones;
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // roman (numerals) grammar
+ //
+ // Note the use of the || operator. The expression
+ // a || b reads match a or b and in sequence. Try
+ // defining the roman numerals grammar in YACC or
+ // PCCTS. Spirit rules! :-)
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_roman_grammar
+ template <typename Iterator>
+ struct roman : qi::grammar<Iterator, unsigned()>
+ {
+ roman() : roman::base_type(start)
+ {
+ using qi::eps;
+ using qi::lit;
+ using qi::_val;
+ using qi::_1;
+ using ascii::char_;
+
+ start = eps [_val = 0] >>
+ (
+ +lit('M') [_val += 1000]
+ || hundreds [_val += _1]
+ || tens [_val += _1]
+ || ones [_val += _1]
+ )
+ ;
+ }
+
+ qi::rule<Iterator, unsigned()> start;
+ };
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tRoman Numerals Parser\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type a Roman Numeral ...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::roman<iterator_type> roman;
+
+ roman roman_parser; // Our grammar
+
+ std::string str;
+ unsigned result;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ //[tutorial_roman_grammar_parse
+ bool r = parse(iter, end, roman_parser, result);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "result = " << result << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ //]
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/sum.cpp b/src/boost/libs/spirit/example/qi/sum.cpp
new file mode 100644
index 00000000..33310aa5
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/sum.cpp
@@ -0,0 +1,106 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A parser for summing a comma-separated list of numbers using phoenix.
+//
+// [ JDG June 28, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+//[tutorial_adder_includes
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <iostream>
+#include <string>
+//]
+
+namespace client
+{
+ //[tutorial_adder_using
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace phoenix = boost::phoenix;
+
+ using qi::double_;
+ using qi::_1;
+ using ascii::space;
+ using phoenix::ref;
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our adder
+ ///////////////////////////////////////////////////////////////////////////
+
+ //[tutorial_adder
+ template <typename Iterator>
+ bool adder(Iterator first, Iterator last, double& n)
+ {
+ bool r = qi::phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[ref(n) = _1] >> *(',' >> double_[ref(n) += _1])
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA parser for summing a list of numbers...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers are added using Phoenix.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ double n;
+ if (client::adder(str.begin(), str.end(), n))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ std::cout << "sum = " << n;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/typeof.cpp b/src/boost/libs/spirit/example/qi/typeof.cpp
new file mode 100644
index 00000000..90e8fb0e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/typeof.cpp
@@ -0,0 +1,65 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ 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 <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/qi_copy.hpp>
+#include <boost/spirit/include/support_auto.hpp>
+#include <iostream>
+#include <string>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+
+int
+main()
+{
+ using boost::spirit::ascii::space;
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::parse;
+ typedef std::string::const_iterator iterator_type;
+
+///////////////////////////////////////////////////////////////////////////////
+// this works for non-c++11 compilers
+#ifdef BOOST_NO_CXX11_AUTO_DECLARATIONS
+
+ BOOST_SPIRIT_AUTO(qi, comment, "/*" >> *(char_ - "*/") >> "*/");
+
+///////////////////////////////////////////////////////////////////////////////
+// but this is better for c++11 compilers with auto
+#else
+
+ using boost::spirit::qi::copy;
+
+ auto comment = copy("/*" >> *(char_ - "*/") >> "*/");
+
+#endif
+
+ std::string str = "/*This is a comment*/";
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = parse(iter, end, comment);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/unescaped_string.cpp b/src/boost/libs/spirit/example/qi/unescaped_string.cpp
new file mode 100644
index 00000000..4a0d6002
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/unescaped_string.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) 2010 Jeroen Habraken
+//
+// 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 <boost/spirit/include/qi.hpp>
+
+#include <iostream>
+#include <ostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ template <typename InputIterator>
+ struct unescaped_string
+ : qi::grammar<InputIterator, std::string(char const*)>
+ {
+ unescaped_string()
+ : unescaped_string::base_type(unesc_str)
+ {
+ unesc_char.add("\\a", '\a')("\\b", '\b')("\\f", '\f')("\\n", '\n')
+ ("\\r", '\r')("\\t", '\t')("\\v", '\v')("\\\\", '\\')
+ ("\\\'", '\'')("\\\"", '\"')
+ ;
+
+ unesc_str = qi::lit(qi::_r1)
+ >> *(unesc_char | qi::alnum | "\\x" >> qi::hex)
+ >> qi::lit(qi::_r1)
+ ;
+ }
+
+ qi::rule<InputIterator, std::string(char const*)> unesc_str;
+ qi::symbols<char const, char const> unesc_char;
+ };
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace qi = boost::spirit::qi;
+
+ typedef std::string::const_iterator iterator_type;
+
+ std::string parsed;
+
+ std::string str("'''string\\x20to\\x20unescape\\x3a\\x20\\n\\r\\t\\\"\\'\\x41'''");
+ char const* quote = "'''";
+
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+
+ client::unescaped_string<iterator_type> p;
+ if (!qi::parse(iter, end, p(quote), parsed))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsed: " << parsed << "\n";
+ std::cout << "-------------------------\n";
+ }
+
+ return 0;
+}