$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
From: joel_at_[hidden]
Date: 2008-04-12 23:02:53
Author: djowel
Date: 2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
New Revision: 44360
URL: http://svn.boost.org/trac/boost/changeset/44360
Log:
spirit2 ! :)
Added:
   trunk/libs/spirit/doc/
   trunk/libs/spirit/doc/Jamfile   (contents, props changed)
   trunk/libs/spirit/doc/_concepts_template_.qbk   (contents, props changed)
   trunk/libs/spirit/doc/_reference_template_.qbk   (contents, props changed)
   trunk/libs/spirit/doc/acknowledgments.qbk   (contents, props changed)
   trunk/libs/spirit/doc/faq.qbk   (contents, props changed)
   trunk/libs/spirit/doc/html/
   trunk/libs/spirit/doc/html/images/
   trunk/libs/spirit/doc/html/images/FlowOfControl.png   (contents, props changed)
   trunk/libs/spirit/doc/html/images/Thumbs.db   (contents, props changed)
   trunk/libs/spirit/doc/html/images/TokenStructure.png   (contents, props changed)
   trunk/libs/spirit/doc/introduction.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/
   trunk/libs/spirit/doc/lex.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/introduction.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_attributes.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_primitives.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_quickstart1.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_quickstart2.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_quickstart3.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_semantic_actions.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_states.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_static_model.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/lexer_tutorials.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/parsing_using_a_lexer.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/token_definition.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/tokenizing.qbk   (contents, props changed)
   trunk/libs/spirit/doc/lex/tokens_values.qbk   (contents, props changed)
   trunk/libs/spirit/doc/notes/
   trunk/libs/spirit/doc/notes.qbk   (contents, props changed)
   trunk/libs/spirit/doc/notes/style_guide.qbk   (contents, props changed)
   trunk/libs/spirit/doc/outline.txt   (contents, props changed)
   trunk/libs/spirit/doc/preface.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/
   trunk/libs/spirit/doc/qi_and_karma.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/attributes.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/debugging.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/directives.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/error_handling.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/generating.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/grammars.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/operators.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/parse_trees_and_asts.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/parsing.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/peg.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/primitives.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/quick_reference.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/rules.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/semantic_actions.qbk   (contents, props changed)
   trunk/libs/spirit/doc/qi_and_karma/tutorials.qbk   (contents, props changed)
   trunk/libs/spirit/doc/rationale.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/
   trunk/libs/spirit/doc/reference/lex/
   trunk/libs/spirit/doc/reference/lex/lexer.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/lex/lexer_class.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/lex/token.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/lex/token_class.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/lex/tokendef.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/lex/tokendef_class.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/lex/tokenset.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/lex/tokenset_class.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/
   trunk/libs/spirit/doc/reference/qi_and_karma/action.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/auxiliary.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/binary.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/char.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/debug.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/directive.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/generator.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/nonterminal.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/numeric.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/operator.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/parser.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/stream.qbk   (contents, props changed)
   trunk/libs/spirit/doc/reference/qi_and_karma/string.qbk   (contents, props changed)
   trunk/libs/spirit/doc/references.qbk   (contents, props changed)
   trunk/libs/spirit/doc/spirit2.qbk   (contents, props changed)
   trunk/libs/spirit/doc/what_s_new.qbk   (contents, props changed)
   trunk/libs/spirit/example/
   trunk/libs/spirit/example/karma/
   trunk/libs/spirit/example/karma/Jamfile   (contents, props changed)
   trunk/libs/spirit/example/karma/basic_facilities.cpp   (contents, props changed)
   trunk/libs/spirit/example/karma/functor_facilities.cpp   (contents, props changed)
   trunk/libs/spirit/example/karma/quick_start1.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/
   trunk/libs/spirit/example/lex/Jamfile   (contents, props changed)
   trunk/libs/spirit/example/lex/example.hpp   (contents, props changed)
   trunk/libs/spirit/example/lex/example1.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/example2.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/example3.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/example4.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/example5.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/example6.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/print_numbers.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/static_lexer/
   trunk/libs/spirit/example/lex/static_lexer/Jamfile   (contents, props changed)
   trunk/libs/spirit/example/lex/static_lexer/word_count_generate.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/static_lexer/word_count_static.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/static_lexer/word_count_static.hpp   (contents, props changed)
   trunk/libs/spirit/example/lex/static_lexer/word_count_tokens.hpp   (contents, props changed)
   trunk/libs/spirit/example/lex/strip_comments.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/strip_comments_lexer.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/word_count.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/word_count_functor.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/word_count_functor_flex.cpp   (contents, props changed)
   trunk/libs/spirit/example/lex/word_count_lexer.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/
   trunk/libs/spirit/example/qi/Jamfile   (contents, props changed)
   trunk/libs/spirit/example/qi/calc1.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc2.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc3.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc3_lexer.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc4.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc5.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc6/
   trunk/libs/spirit/example/qi/calc6/calc6.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc6/calc6.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc6/calc6a.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc6/calc6b.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc6/calc6b.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc6/calc6c.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc6/calc6c.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc7/
   trunk/libs/spirit/example/qi/calc7/calc7.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc7/calc7.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc7/calc7a.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc7/calc7b.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc7/calc7b.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc7/calc7c.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/calc7/calc7c.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/complex_number.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/employee.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/
   trunk/libs/spirit/example/qi/mini_c/mini_c.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/mini_c.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/mini_ca.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/mini_cb.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/mini_cb.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/mini_cc.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/mini_cc.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/mini_cd.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c/mini_cd.hpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_c_samples/
   trunk/libs/spirit/example/qi/mini_xml1.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_xml2.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_xml_karma.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_xml_samples/
   trunk/libs/spirit/example/qi/mini_xml_samples/1.xml   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_xml_samples/2.xml   (contents, props changed)
   trunk/libs/spirit/example/qi/mini_xml_samples/3.xml   (contents, props changed)
   trunk/libs/spirit/example/qi/num_list.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/num_list2.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/num_list3.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/roman.cpp   (contents, props changed)
   trunk/libs/spirit/example/qi/sum.cpp   (contents, props changed)
   trunk/libs/spirit/index.html   (contents, props changed)
   trunk/libs/spirit/phoenix/
   trunk/libs/spirit/phoenix/doc/
   trunk/libs/spirit/phoenix/doc/Jamfile.v2   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/
   trunk/libs/spirit/phoenix/doc/html/boostbook.css   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/
   trunk/libs/spirit/phoenix/doc/html/images/add2.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/add2_call.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/adder.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/alert.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/banner.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/fbox.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/funnel_in.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/funnel_out.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/home.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/lambda_cpp.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/next.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/note.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/organization.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/prev.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/smiley.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/tip.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/images/up.png   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/index.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/
   trunk/libs/spirit/phoenix/doc/html/phoenix/acknowledgement.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/actors.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/algorithm.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/basics.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/composite.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/inside_phoenix.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/intrinsic.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/introduction.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/organization.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/primitives.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/references.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/starter_kit.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/html/phoenix/wrap_up.html   (contents, props changed)
   trunk/libs/spirit/phoenix/doc/users_manual.qbk   (contents, props changed)
   trunk/libs/spirit/phoenix/example/
   trunk/libs/spirit/phoenix/example/Jamfile.v2   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/
   trunk/libs/spirit/phoenix/example/users_manual/algorithm.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/all_odds.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/arguments.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/callback.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/factorial.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/find_if.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/function.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/if.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/lambda.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/references.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/example/users_manual/values.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/index.html   (contents, props changed)
   trunk/libs/spirit/phoenix/test/
   trunk/libs/spirit/phoenix/test/Jamfile.v2   (contents, props changed)
   trunk/libs/spirit/phoenix/test/algorithm/
   trunk/libs/spirit/phoenix/test/algorithm/iteration.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/algorithm/querying.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/algorithm/querying2.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/algorithm/transformation1.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/algorithm/transformation2.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/algorithm/transformation3.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/algorithm/transformation4.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/bind/
   trunk/libs/spirit/phoenix/test/bind/bind_function_object_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/bind/bind_function_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/bind/bind_member_function_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/bind/bind_member_variable_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/
   trunk/libs/spirit/phoenix/test/container/container_tests.hpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests1a.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests1b.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests2a.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests2b.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests3a.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests3b.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests4a.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests4b.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests5a.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests5b.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests6a.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/container/container_tests6b.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/core/
   trunk/libs/spirit/phoenix/test/core/compose_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/core/primitives_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/detail/
   trunk/libs/spirit/phoenix/test/detail/type_deduction_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/function/
   trunk/libs/spirit/phoenix/test/function/function_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/object/
   trunk/libs/spirit/phoenix/test/object/cast_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/object/new_delete_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/
   trunk/libs/spirit/phoenix/test/operator/arithmetic_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/bitwise_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/comparison_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/if_else_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/io_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/logical_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/member.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/misc_binary_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/self_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/operator/unary_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/scope/
   trunk/libs/spirit/phoenix/test/scope/bug_000008.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/scope/dynamic_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/scope/lambda_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/scope/let_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/statement/
   trunk/libs/spirit/phoenix/test/statement/exceptions.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/statement/if_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/statement/loops_tests.cpp   (contents, props changed)
   trunk/libs/spirit/phoenix/test/statement/switch_tests.cpp   (contents, props changed)
   trunk/libs/spirit/test/
   trunk/libs/spirit/test/Jamfile   (contents, props changed)
   trunk/libs/spirit/test/karma/
   trunk/libs/spirit/test/karma/alternative.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/binary.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/case_handling.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/center_alignment.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/char.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/delimiter.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/eps.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/format_manip.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/functor.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/grammar.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/grammar_fail.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/int_numerics.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/kleene.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/lazy.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/left_alignment.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/list.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/lit.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/none.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/optional.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/pattern.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/real_numerics.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/right_alignment.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/rule_fail.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/sequence.cpp   (contents, props changed)
   trunk/libs/spirit/test/karma/test.hpp   (contents, props changed)
   trunk/libs/spirit/test/lex/
   trunk/libs/spirit/test/lex/lexertl1.cpp   (contents, props changed)
   trunk/libs/spirit/test/lex/lexertl2.cpp   (contents, props changed)
   trunk/libs/spirit/test/lex/lexertl3.cpp   (contents, props changed)
   trunk/libs/spirit/test/lex/lexertl4.cpp   (contents, props changed)
   trunk/libs/spirit/test/lex/lexertl5.cpp   (contents, props changed)
   trunk/libs/spirit/test/lex/state_switcher_test.cpp   (contents, props changed)
   trunk/libs/spirit/test/lex/test.hpp   (contents, props changed)
   trunk/libs/spirit/test/lex/test_parser.hpp   (contents, props changed)
   trunk/libs/spirit/test/qi/
   trunk/libs/spirit/test/qi/alternative.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/and_predicate.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/binary.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/char.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/char_class.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/debug.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/difference.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/eps.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/expect.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/functor.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/grammar.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/grammar_fail.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/int.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/kleene.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/lazy.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/lexeme.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/list.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/lit.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/match_manip.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/no_case.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/none.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/not_predicate.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/optional.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/permutation.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/plus.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/range_run.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/raw.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/real.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/rule.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/rule_fail.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/sequence.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/sequential_or.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/symbols.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/test.hpp   (contents, props changed)
   trunk/libs/spirit/test/qi/tst.cpp   (contents, props changed)
   trunk/libs/spirit/test/qi/uint.cpp   (contents, props changed)
   trunk/libs/spirit/test/support/
   trunk/libs/spirit/test/support/detail/
   trunk/libs/spirit/test/support/detail/sstream.hpp   (contents, props changed)
   trunk/libs/spirit/test/support/hold_any.cpp   (contents, props changed)
   trunk/libs/spirit/test/support/multi_pass.cpp   (contents, props changed)
   trunk/libs/spirit/test/support/multi_pass_compile.cpp   (contents, props changed)
Text files modified: 
   trunk/libs/spirit/classic/test/bug_000008.cpp |     2 +-                                      
   1 files changed, 1 insertions(+), 1 deletions(-)
Modified: trunk/libs/spirit/classic/test/bug_000008.cpp
==============================================================================
--- trunk/libs/spirit/classic/test/bug_000008.cpp	(original)
+++ trunk/libs/spirit/classic/test/bug_000008.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -11,7 +11,7 @@
   // or https://sf.net/mailarchive/forum.php?thread_id=2692308&forum_id=1595
   // for a description of the bug being tested for by this program
   //
-  // the problem should be solved with version 1.3 of phoenix/closures.hpp
+  // the problem should be solved with version 1.3 of phoenix/closures.hpp>
 
 #if defined(BOOST_SPIRIT_DEBUG) && defined(__GNUC__) && defined(__WIN32__)
 // It seems that MinGW has some problems with threads and iostream ?
Added: trunk/libs/spirit/doc/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/Jamfile	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,27 @@
+#==============================================================================
+#   Copyright (c) 2001-2007 Joel de Guzman
+#   Copyright (c) 2001-2007 Hartmut Kaiser
+#
+#   Use, modification and distribution is subject to the Boost Software
+#   License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+#   http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+
+project spirit/doc ;
+
+import boostbook : boostbook ;
+using quickbook : quickbook ;
+
+boostbook spirit2
+    :
+        spirit2.qbk
+    :
+        <xsl:param>boost.root=../../../..
+        <xsl:param>boost.libraries=../../../libraries.htm
+        <xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
+        <xsl:param>chunk.section.depth=5
+        <xsl:param>chunk.first.sections=1
+        <xsl:param>toc.section.depth=4
+        <xsl:param>toc.max.depth=4
+        <xsl:param>generate.section.toc.level=4
+    ;
Added: trunk/libs/spirit/doc/_concepts_template_.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/_concepts_template_.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,46 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section XXX]
+
+[heading Description]
+
+Description of XXX concept
+
+[variablelist Notation
+    [[`xxx`]     [An XXX]]
+]
+
+[heading Valid Expressions]
+
+(For any Forward Sequence the following expressions must be valid:)
+
+In addition to the requirements defined in _XXX-Basic_concept_, for any
+XXX the following must be met:
+
+[table
+    [[Expression]       [Semantics]             [Return type]       [Complexity]]
+    [[`xxx`]            [Semantics of `xxx`]    [XXX]               [Constant]]
+]
+
+[heading Type Requirements]
+
+[table
+    [[Expression]       [Requirements]]
+    [[`xxx`]            [Requirements for `xxx`]]
+]
+
+[heading Invariants]
+
+For any XXX xxx the following invariants always hold:
+
+[heading Models]
+
+Links to models of XXX concept
+
+[endsect]
Added: trunk/libs/spirit/doc/_reference_template_.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/_reference_template_.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,56 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section XXX]
+
+[heading Description]
+
+Description of XXX
+
+[heading Header]
+
+    #include <boost/spirit/xxx.hpp>
+
+[heading Synopsis]
+
+    template <typename T>
+    struct XXX;
+
+[heading Template parameters]
+
+[table
+    [[Parameter]            [Description]               [Default]]
+    [[`T`]                  [What is T]                 []]
+]
+
+[heading Model of]
+
+Link to concept
+
+[heading Objects]
+
+Objects provided by the library
+
+[variablelist Notation
+    [[`xxx`]     [An XXX]]
+]
+
+Semantics of an expression is defined only where it differs from, or is not
+defined in _concept-of_XXX_.
+
+[table
+    [[Expression]       [Semantics]             [Return type]       [Complexity]]
+    [[`xxx`]            [Semantics of `xxx`]    [XXX]               [Constant]]
+]
+
+[heading Example]
+
+Real example code. Use Quickbook import mechanism to link to actual
+working code snippets here.
+
+[endsect]
Added: trunk/libs/spirit/doc/acknowledgments.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/acknowledgments.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,147 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Acknowledgments]
+
+This version of Spirit is a complete rewrite of the /classic/ Spirit many 
+people have been contributing to (see below). But there are a couple of people 
+who already managed to help significantly during this rewrite. We would like to 
+express our special acknowledgement to:
+
+[*Eric Niebler] for writing Boost.Proto, without which this rewrite wouldn't 
+have been possible, and helping with examples, advices, and suggestions on
+how to use Boost.Proto in the best possible way.
+
+[*Ben Hanson] for providing us with an early version of his Lexertl library, 
+which is proposed to be included into Boost (as Boost.Lexer), but at the time 
+of this writing the Boost review for this library is still pending.
+
+__fixme__: Add more people
+
+
+[heading Acknowledgements from the Spirit V1 /classic/ Documentation]
+
+Special thanks for working on Spirit /classic/ to:
+
+[*Dan Nuffer] for his work on lexers, parse trees, ASTs, XML parsers, the 
+multi-pass iterator as well as administering Spirit's site, editing, 
+maintaining the CVS and doing the releases plus a zillion of other chores that 
+were almost taken for granted. 
+
+[*Hartmut Kaiser] for his work on the C parser, the work on the C/C++ 
+preprocessor, utility parsers, the original port to Intel 5.0, various work on 
+Phoenix, porting to v1.5, the meta-parsers, the grouping-parsers, extensive 
+testing and painstaking attention to details.
+
+[*Martin Wille] who improved grammar multi thread safety, contributed the eol_p 
+parser, the dynamic parsers, documentation and for taking an active role in 
+almost every aspect from brainstorming and design to coding. And, as always, 
+helps keep the regression tests for g++ on Linux as green as ever :-). 
+
+[*Martijn W. Van Der Lee] our Web site administrator and for contributing the 
+RFC821 parser.
+
+[*Giovanni Bajo] for last minute tweaks of Spirit 1.8.0 for CodeWarrior 8.3. 
+Actually, I'm ashamed Giovanni was not in this list already. He's done a lot 
+since Spirit 1.5, the first Boost.Spirit release. He's instrumental in the 
+porting of the Spirit iterators stuff to the new Boost Iterators Library 
+(version 2). He also did various bug fixes and wrote some tests here and there. 
+
+[*Juan Carlos Arevalo-Baeza (JCAB)*] for his work on the C++ parser, the position 
+iterator, ports to v1.5 and keeping the mailing list discussions alive and 
+kicking.
+
+[*Vaclav Vesely], lots of stuff, the no\_actions directive, various patches 
+fixes, the distinct parsers, the lazy parser, some phoenix tweaks and add-ons 
+(e.g. new\_). Also, *Stefan Slapeta] and wife for editing Vaclav's distinct 
+parser doc. 
+
+[*Raghavendra Satish] for doing the original v1.3 port to VC++ and his work on 
+Phoenix.
+
+[*Noah Stein] for following up and helping Ragav on the VC++ ports.
+
+[*Hakki Dogusan], for his original v1.0 Pascal parser.
+
+[*John (EBo) David] for his work on the VM and watching over my shoulder as I 
+code giving the impression of distance eXtreme programming.
+
+[*Chris Uzdavinis] for feeding in comments and valuable suggestions as well as 
+editing the documentation.
+
+[*Carsten Stoll], for his work on dynamic parsers.
+
+[*Andy Elvey] and his conifer parser.
+
+[*Bruce Florman], who did the original v1.0 port to VC++.
+
+[*Jeff Westfahl] for porting the loop parsers to v1.5 and contributing the file 
+iterator.
+
+[*Peter Simons] for the RFC date parser example and tutorial plus helping out 
+with some nitty gritty details.
+
+[*Markus Sch'''ö'''pflin] for suggesting the end_p parser and lots of other 
+nifty things and his active presence in the mailing list.
+
+[*Doug Gregor] for mentoring and his ability to see things that others don't. 
+
+[*David Abrahams] for giving Joel a job that allows him to still work on Spirit, 
+plus countless advice and help on C++ and specifically template 
+metaprogramming.
+
+[*Aleksey Gurtovoy] for his MPL library from which we stole many metaprogramming 
+tricks especially for less conforming compilers such as Borland and VC6/7.
+
+[*Gustavo Guerra] for his last minute review of Spirit and constant feedback, 
+plus patches here and there (e.g. proposing the new dot behavior of the real 
+numerics parsers).
+
+[*Nicola Musatti], [*Paul Snively], [*Alisdair Meredith] and [*Hugo Duncan] for 
+testing and sending in various patches.
+
+[*Steve Rowe] for his splendid work on the TSTs that will soon be taken into 
+Spirit.
+
+[*Jonathan de Halleux] for his work on actors.
+
+[*Angus Leeming] for last minute editing work on the 1.8.0 release 
+documentation, his work on Phoenix and his active presence in the Spirit 
+mailing list.
+
+[*Joao Abecasis] for his active presence in the Spirit mailing list, providing 
+user support, participating in the discussions and so on. 
+
+[*Guillaume Melquiond] for a last minute patch to multi_pass for 1.8.1. 
+
+[*Peder Holt] for his porting work on Phoenix, Fusion and Spirit to VC6. 
+
+To Joels wife Mariel who did the graphics in this document.
+
+My, there's a lot in this list! And it's a continuing list. We add people to 
+this list everytime. We hope we did not forget anyone. If we missed
+someone you know who has helped in any way, please inform us.
+
+Special thanks also to people who gave feedback and valuable comments, 
+particularly members of Boost and Spirit mailing lists. This includes all those 
+who participated in the review:
+
+[*John Maddock], our review manager, [*Aleksey Gurtovoy], [*Andre Hentz],
+[*Beman Dawes], [*Carl Daniel], [*Christopher Currie], [*Dan Gohman],
+[*Dan Nuffer], [*Daryle Walker], [*David Abrahams], [*David B. Held],
+[*Dirk Gerrits], [*Douglas Gregor], [*Hartmut Kaiser], [*Iain K.Hanson],
+[*Juan Carlos Arevalo-Baeza], [*Larry Evans], [*Martin Wille], 
+[*Mattias Flodin], [*Noah Stein], [*Nuno Lucas], [*Peter Dimov],
+[*Peter Simons], [*Petr Kocmid], [*Ross Smith], [*Scott Kirkwood],
+[*Steve Cleary], [*Thorsten Ottosen], [*Tom Wenisch], [*Vladimir Prus]
+
+Finally thanks to SourceForge for hosting the Spirit project and Boost: a C++ 
+community comprised of extremely talented library authors who participate in 
+the discussion and peer review of well crafted C++ libraries.
+
+[endsect]
Added: trunk/libs/spirit/doc/faq.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/faq.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section FAQ]
+[endsect]
Added: trunk/libs/spirit/doc/html/images/FlowOfControl.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/doc/html/images/Thumbs.db
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/doc/html/images/TokenStructure.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/doc/introduction.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/introduction.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Introduction]
+[endsect]
Added: trunk/libs/spirit/doc/lex.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,50 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section __lex__]
+
+[include    lex/introduction.qbk]
+
+[section __lex__ Tutorials]
+[include        lex/lexer_tutorials.qbk]
+[include        lex/lexer_quickstart1.qbk]
+[include        lex/lexer_quickstart2.qbk]
+[include        lex/lexer_quickstart3.qbk]
+[endsect]
+
+[section Abstracts]
+[section        Lexer Primitives]
+[include            lex/lexer_primitives.qbk]
+[include            lex/tokens_values.qbk]
+[include            lex/token_definition.qbk]
+[endsect]
+[include        lex/tokenizing.qbk]
+[include        lex/lexer_semantic_actions.qbk]
+[include        lex/lexer_static_model.qbk]
+[include        lex/parsing_using_a_lexer.qbk]
+[include        lex/lexer_attributes.qbk]
+[include        lex/lexer_states.qbk]
+[endsect]
+
+[section Quick Reference]
+[endsect]
+
+[section Reference]
+[section        Concepts]
+[include            reference/lex/lexer.qbk]
+[include            reference/lex/token.qbk]
+[include            reference/lex/tokendef.qbk]
+[include            reference/lex/tokenset.qbk]
+[endsect]
+[include        reference/lex/lexer_class.qbk]
+[include        reference/lex/token_class.qbk]
+[include        reference/lex/tokendef_class.qbk]
+[include        reference/lex/tokenset_class.qbk]
+[endsect]
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/introduction.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/introduction.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,137 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Introduction to __lex__]
+
+Lexical scanning is the process of analyzing the stream of input characters and 
+separating it into strings called tokens, separated by whitespace. 
+Most compiler texts start here, and devote several chapters to discussing 
+various ways to build scanners. __lex__ is a library built to take care of the 
+complexities of creating a lexer for your grammar (in this documentation we 
+will use the terms 'lexical analyzer', 'lexer' and 'scanner' interchangably). 
+All it needs to create a lexer is to know the set of patterns describing the 
+different tokens you want to recognize in the input. To make this a bit more 
+formal, here are some definitions:
+
+* A token is a sequence of consecutive characters having a collective meaning.
+  Tokens may have attributes specific to the token type, carrying additional
+  information about the matched character sequence.
+* A pattern is a rule expressed as a regular expression and describing how a 
+  particular token can be formed. For example, [^\[A-Za-z\]\[A-Za-z_0-9\]*] is 
+  a pattern for a rule matching C++ identifiers.
+* Characters between tokens are called whitespace; these include spaces, tabs, 
+  newlines, and formfeeds. Many people also count comments as whitespace, 
+  though since some tools such as lint look at comments, this conflation is not 
+  perfect.
+
+[heading Why Using a Separate Lexer]
+
+Typically, lexical scanning is done in a separate module from the parser, 
+feeding the parser with a stream of input tokens only. Now, theoretically it is 
+not necessary to do this separation. In the end there is only one set of 
+syntactical rules defining the language, so in theory we could write the whole 
+parser in one module. In fact, __qi__ allows to write parsers without using a 
+lexer, parsing the input character stream directly, and for the most part this 
+is the way __spirit__ has been used since its invention.
+
+However, the separation has both practical and theoretical bases and proves to 
+be very useful in practical applications. In 1956, Noam Chomsky defined the 
+"Chomsky Hierarchy" of grammars:
+
+* Type 0:  Unrestricted grammars (e.g., natural languages)
+* Type 1:  Context-Sensitive grammars
+* Type 2:  Context-Free grammars
+* Type 3:  Regular grammars
+
+The complexity of these grammars increases from regular grammars being the 
+simplest to unrestricted grammars being the most complex. Similarily, the 
+complexity of the recognizers for these grammars increases. Although, a few 
+features of some programming languages (such as C++) are Type 1, fortunately 
+for the most part programming languages can be described using only the Types 3 
+and 2. The neat part about these two types is that they are well known and the 
+ways to parse them are well understood. It has been shown that any regular 
+grammar can be parsed using a state machine (finite automaton). Similarly, 
+context-free grammars can always be parsed using a push-down automaton 
+(essentially a state machine augmented by a stack). 
+
+In real programming languages and practical grammars the parts that can be 
+handled as regular expressions tend to be the lower-level parts, such as the 
+definition of an identifier or of an integer value:
+
+    letter     := [a-zA-Z]
+    digit      := [0-9]
+    
+    identifier := letter [ letter | digit ]*
+    integer    := digit*
+
+Higher level parts of practical grammars tend to be more complex and can't be
+implemented using plain regular expressions anymore. We need to store 
+information on the built-in hardware stack while recursing the grammar 
+hierarchy, and that in fact this is the preferred approach used for top-down 
+parsing. Since it takes a different kind of abstract machine to parse the two 
+types of grammars, it proved to be efficient to separate the lexical scanner 
+into a separate module which is built around the idea of a state machine. The 
+goal here is to use the simplest parsing technique needed for the job.
+
+Another, more practical reason for separating the scanner from the parser is
+the need for backtracking during parsing. The input data is a stream of 
+characters, which is often thought to be processed left to right without any 
+backtracking. Unfortunately, in practice most of the time that isn't possible.
+Almost every language has certain keywords such as IF, FOR, and WHILE. The 
+decision if a certain character sequence actually comprises a keyword or just 
+an identifier often can be made only after seeing the first delimiter /after/
+it. This already is a limited form of backtracking, since we need to store the 
+string long enough to be able to make the decision. The same is true for more 
+coarse grained language features such as nested IF/ELSE statements, where the 
+decision about to which IF belongs the last ELSE statement can be made only
+after seeing the whole construct.
+
+So the structure of a conventional compiler often involves splitting up the 
+functions of the lower-level and higher-level parsing. The lexical scanner 
+deals with things at the character level, collecting characters into strings, 
+converting character sequence into different representations as integers, etc., 
+and passing them along to the parser proper as indivisible tokens. It's also 
+considered normal to let the scanner do additional jobs, such as identifying 
+keywords, storing identifiers in tables, etc. 
+
+Now, __spirit__ follows this structure, where __lex__ can be used to implement 
+state machine based recognizers, while __qi__ can be used to build recognizers 
+for context free grammars. Since both modules are seemlessly integrated with 
+each other and with the C++ target language it is even possible to use the 
+provided functionality to build more complex grammar recognizers.
+
+[heading Advantages of using __lex__]
+
+The advantage of using __lex__ to create the lexical analyzer over using more 
+traditional tools such as __flex__ is its carefully crafted integration with 
+the __spirit__ library and the C++ host language. You don't need any external 
+tools to generate the code, your lexer will be perfectly integrated with the 
+rest of your program, making it possible to freely access any context 
+information and data structure. Since the C++ compiler sees all the code it
+will generate optimal code nomatter what configuration options have been chosen
+by the user. __lex__ gives you all the features you could get from a similar
+__flex__ program without the need to leave C++ as a host language:
+
+* the definition of tokens is done using regular expressions (patterns)
+* the token definitions can refer to special substitution string (pattern 
+  macros) simplifying pattern definitions
+* the generated lexical scanner may have multiple start states
+* it is possible to attach code to any of the token definitions; this code gets
+  executed whenever the corresponding token pattern has been matched
+
+Even if it is possible to use __lex__ to generate C++ code representing 
+the lexical analyzer (we will refer to that as the /static/ model, described in 
+more detail in the section __sec_lex_static_model__) - a model
+very similar to the way __flex__ operates - we will mainly focus on the 
+opposite, the /dynamic/ model. You can directly integrate the token definitions 
+into your C++ program, building the lexical analyzer dynamicly at runtime. The 
+dynamic model is something not supported by __flex__ or other lexical scanner 
+generators (such as __re2c__, __ragel__, etc.). But it is very flexible and 
+allows to speed up the development of your application.
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_attributes.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_attributes.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,12 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Lexer Attributes]
+
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_primitives.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_primitives.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,15 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Lexer Primitives]
+
+[/ Describe the primitive lexer constructs, such as token_def, token_set? ]
+[/ Describe the primitive lexer constructs usable in parsers, such as 
+   in_state[], set_state(), token(), etc. ]
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_quickstart1.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_quickstart1.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,97 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Quickstart 1 - A word counter using __lex__]
+
+__lex__ is very modular, which follows the general building principle of the 
+__spirit__ libraries. You never pay for features you don't use. It is nicely 
+integrated with the other parts of __spirit__ but nevertheless can be used 
+separately to build standalone lexical analyzers. 
+The first quick start example describes a standalone application: 
+counting characters, words and lines in a file, very similar to what the well 
+known Unix command `wc` is doing (for the full example code see here:
+[@../../example/lex/word_count_functor.cpp word_count_functor.cpp]).
+
+[import ../example/lex/word_count_functor.cpp]
+
+
+[heading Prerequisites]
+
+The only required `#include` specific to /Spirit.Lex/ follows. It is a wrapper 
+for all necessary definitions to use /Spirit.Lex/ in a standalone fashion, and 
+on top of the __lexertl__ library. Additionally we `#include` two of the Boost 
+headers to define `boost::bind()` and `boost::ref()`.
+
+[wcf_includes]
+
+To make all the code below more readable we introduce the following namespaces.
+
+[wcf_namespaces]
+
+
+[heading Defining Tokens]
+
+The most important step while creating a lexer using __lex__ is to define the 
+tokens to be recognized in the input sequence. This is normally done by 
+defining the regular expressions describing the matching character sequences, 
+and optionally their corresponding token ids. Additionally the defined tokens 
+need to be associated with an instance of a lexer object as provided by the 
+library. The following code snippet shows how this can be done using __lex__.
+
+[wcf_token_definition]
+
+
+[heading Doing the Useful Work]
+
+We will use a setup, where we want the __lex__ library to invoke a given 
+function after any of of the generated tokens is recognized. For this reason 
+we need to implement a functor taking at least the generated token as an 
+argument and returning a boolean value allowing to stop the tokenization 
+process. The default token type used in this example carries a token value of
+the type `iterator_range<BaseIterator>` pointing to the matched range in the 
+underlying input sequence. 
+
+[wcf_functor]
+
+All what's left is to write some boilerplate code helping to tie together the
+pieces described so far. To simplify this example we call the `lex::tokenize()`
+function implemented in __lex__ (for a more detailed description of this 
+function see here: __fixme__), even if we could have written a loop to iterate
+over the lexer iterators [`first`, `last`) as well.
+
+
+[heading Pulling Everything Together]
+
+[wcf_main]
+
+
+[heading Comparing __lex__ with __flex__]
+
+This example was deliberately chosen to be similar as much as possible to the 
+equivalent __flex__ program (see below), which isn't too different from what 
+has to be written when using __lex__. 
+
+[note   Interestingly enough, performance comparisons of lexical analyzers 
+        written using __lex__ with equivalent programs generated by 
+        __flex__ show that both have comparable execution speeds! 
+        Generally, thanks to the highly optimized __lexertl__ library and 
+        due its carefully designed integration with __spirit__ the 
+        abstraction penalty to be paid for using __lex__ is neglectible.
+]
+
+The remaining examples in this tutorial will use more sophisticated features 
+of __lex__, mainly to allow further simplification of the code to be written, 
+while maintaining the similarity with corresponding features of __flex__. 
+__lex__ has been designed to be as much as possible similar to __flex__, that 
+is why this documentation will provide the corresponding __flex__ code for the 
+shown __lex__ examples almost everywhere. So consequently, here is the __flex__ 
+code corresponding to the example as shown above.
+
+[wcf_flex_version]
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_quickstart2.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_quickstart2.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,133 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Quickstart 2 - A better word counter using __lex__]
+
+People knowing __flex__ will probably complain about the example from the 
+section __sec_lex_quickstart_1__ as being overly complex and not being 
+written to leverage the possibilities provided by this tool. In particular the
+previous example did not directly use the lexer actions to count the lines, 
+words and characters. So the example provided in this step of the tutorial will 
+show how to use semantic actions in __lex__. Even if it still  
+will allow to count text elements only it introduces other new concepts and 
+configuration options along the lines (for the full example code 
+see here: [@../../example/lex/word_count_lexer.cpp word_count_lexer.cpp]).
+
+[import ../example/lex/word_count_lexer.cpp]
+
+
+[heading Prerequisites]
+
+In addition to the only required `#include` specific to /Spirit.Lex/ this 
+example needs to include a couple of header files from the __phoenix2__ 
+library. This example shows how to attach functors to token definitions, which 
+could be done using any type of C++ technique resulting in a callable object.
+Using __phoenix2__ for this task simplifies things and avoids adding 
+dependencies to other libraries (__phoenix2__ is already in use for 
+__spirit__ anyway).
+
+[wcl_includes]
+
+To make all the code below more readable we introduce the following namespaces.
+
+[wcl_namespaces]
+
+To give a preview at what to expect from this example, here is the flex program
+which has been used as the starting point. The useful code is directly included 
+inside the actions associated with each of the token definitions. 
+
+[wcl_flex_version]
+
+
+[heading Semantic Actions in __lex__]
+
+__lex__ uses a very similar way of associating actions with the token 
+definitions (which should look familiar to anybody knowlegdeable with 
+__spirit__ as well): specifying the operations to execute inside of a pair of
+`[]` brackets. In order to be able to attach semantic actions to token 
+definitions for each of them there is defined an instance of a `token_def<>`.
+
+[wcl_token_definition]
+
+The semantics of the shown code is as follows. The code inside the `[]` 
+brackets will be executed whenever the corresponding token has been matched by 
+the lexical analyzer. This is very similar to __flex__, where the action code 
+associated with a token definition gets executed after the recognition of a
+matching input sequence. The code above uses functors constructed using 
+__phoenix2__, but it is possible to insert any C++ functor as long as it 
+exposes the interface:
+
+    void f (Range r, std::size_t id, Context& ctx, bool& matched);
+
+[variablelist where:
+    [[`Range r`]            [This is a `boost::iterator_range` holding two 
+                             iterators pointing to the matched range in the
+                             underlying input sequence. The type of the
+                             held iterators is the same as specified while
+                             defining the type of the `lexertl_lexer<...>` 
+                             (its first template parameter).]]
+    [[`std::size_t id`]     [This is the token id for the matched token.]]
+    [[`Context& ctx`]       [This is a reference to a lexer specific, 
+                             unspecified type, providing the context for the
+                             current lexer state. It can be used to access
+                             different internal data items and is needed for
+                             lexer state control from inside a semantic 
+                             action.]]
+    [[`bool& matched`]      [This boolean value is pre/initialized to `true`.
+                             If the functor sets it to `false` the lexer
+                             stops calling any semantic actions attached to 
+                             this token and behaves as if the token have not
+                             been matched in the first place.]]
+]
+
+Even if it is possible to write your own functor implementations, the preferred 
+way of defining lexer semantic actions is to use __phoenix2__. In this case you
+can access the three parameters described in the table above by using the 
+predefined __phoenix2__ placeholders: `_1` for the iterator range, `_2` for the 
+token id, `_3` for the reference to the lexer state, and `_4` for the reference 
+to the boolean value signaling the outcome of the semantic action. 
+
+[important  All placeholders (`_1`, `_2`, etc.) used in /lexer/ semantic 
+            actions in conjunction with functors created based on __phoenix2__ 
+            need to be imported from the `namespace boost::phoenix::arg_names` 
+            (and *not* `namespace boost::spirit::arg_names`, which is 
+            different from using placeholders in __qi__ or __karma__). 
+            Using the wrong placeholders leads to subtle compilation errors 
+            which are difficult to backtrack to their cause.
+]
+
+
+[heading Associating Token Definitions with the Lexer]
+
+If you compare the with the code from __sec_lex_quickstart_1__ with regard to 
+the way how token definitions are associated with the lexer, you will notice 
+a different syntax being used here. If in the previous example we have been 
+using the `self.add()` style of the API, then here we directly assign the token 
+definitions to `self`, combining the different token definitions using the `|` 
+operator. Here is the code snippet again:
+
+    self =  word  [++ref(w), ref(c) += distance(_1)]
+        |   eol   [++ref(c), ++ref(l)] 
+        |   any   [++ref(c)]
+        ;
+
+This way we have a very powerful and natural way of building the lexical 
+analyzer. If translated into English this may be read as: The lexical analyer 
+will recognize ('`=`') tokens as defined by any of ('`|`') the token 
+definitions `word`, `eol`, and `any`. 
+
+A second difference to the previous example is that we do not explicitly 
+specify any token ids to use for the separate tokens. Using semantic actions to 
+trigger some useful work free'd us from the need to define these. To ensure 
+every token gets assigned a id the __lex__ library internally assigns unique 
+numbers to the token definitions, starting with the constant defined by 
+`boost::spirit::lex::min_token_id`.
+
+
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_quickstart3.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_quickstart3.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,151 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Quickstart 3 - Counting Words Using a Parser]
+
+The whole purpose of integrating __lex__ as part of the __spirit__ library was 
+to add a library allowing to merge lexical analysis with the parsing 
+process as defined by a __spirit__ grammar. __spirit__ parsers read their input 
+from an input sequence accessed by iterators. So naturally, we chose iterators 
+to be used as the interface beween the lexer and the parser. A second goal of 
+the lexer/parser integration was to enable the usage of possibly different 
+lexical analyzer libraries. The utilization of iterators seemed to be the 
+right choice from this standpoint as well, mainly because these can be used as
+an abstraction layer hiding implementation specifics of the used lexer 
+library. The [link spirit.lex.flowcontrol picture] below shows the common 
+flow control implemented while parsing combined with lexical analysis.
+
+[fig ./images/FlowOfControl.png..The common flow control implemented while parsing combined with lexical analysis..spirit.lex.flowcontrol]
+
+Another problem related to the integration of the lexical analyzer with the 
+parser was to find a way how the defined tokens syntactically could be blended
+with the grammar definition syntax of __spirit__. For tokens defined as 
+instances of the `token_def<>` class the most natural way of integration was 
+to allow to directly use these as parser components. Semantically these parser
+components succeed matching their input whenever the corresponding token type
+has been matched by the lexer. This quick start example will demonstrate this
+(and more) by counting words again, simply by adding up the numbers inside
+of semantic actions of a parser (for the full example code see here: 
+[@../../example/lex/word_count.cpp word_count.cpp]).
+
+
+[import ../example/lex/word_count.cpp]
+
+
+[heading Prerequisites]
+
+This example uses two of the __spirit__ library components: __lex__ and __qi__,
+consequently we have to `#include` the corresponding header files. Again, we
+need to include a couple of header files from the __phoenix2__ library. This 
+example shows how to attach functors to parser components, which 
+could be done using any type of C++ technique resulting in a callable object.
+Using __phoenix2__ for this task simplifies things and avoids adding 
+dependencies to other libraries (__phoenix2__ is already in use for 
+__spirit__ anyway).
+
+[wcp_includes]
+
+To make all the code below more readable we introduce the following namespaces.
+
+[wcp_namespaces]
+
+
+[heading Defining Tokens]
+
+If compared to the two previous quick start examples (__sec_lex_quickstart_1__
+and __sec_lex_quickstart_2__) the token definition class for this example does 
+not reveal any surprises. However, it uses lexer token definition macros to 
+simplify the composition of the regular expressions, which will be described in 
+more detail in the section __fixme__. Generally, any token definition is usable
+without modification either for a standalone lexical analyzer or in conjunction
+with a parser.
+
+[wcp_token_definition]
+
+
+[heading Using Token Definition Instances as Parsers]
+
+While the integration of lexer and parser in the control flow is achieved by 
+using special iterators wrapping the lexical analyzer, we still nead a means of
+expressing in the grammar what tokens to match and where. The token definition 
+class above uses three different ways of defining a token:
+
+* Using an instance of a `token_def<>`, which is handy whenever you need to 
+  specify a token attribute (for more information about lexer related 
+  attributes please look here: __sec_lex_attributes__).
+* Using a single character as the token, in this case the character represents
+  itself as a token, where the token id is the ASCII character value.
+* Using a regular expression represented as a string, where the token id needs 
+  to be specified explicitly to make the token accessible from the grammar 
+  level.
+
+All three token definition methods require a different method of grammar 
+integration. But as you can see from the following code snippet, each of this 
+methods is straightforward and blends the corresponding token instance 
+naturally with the surrounding __qi__ grammar syntax.
+
+[table
+    [[Token definition]   [Parser integration]]
+    [[`token_def<>`]      [The `token_def<>` instance is directly usable as a 
+                           parser component. Parsing of this component will 
+                           succeed if the regular expression used to define 
+                           this has been matched successfully.]]
+    [[single character]   [The single character is directly usable in the 
+                           grammar, under certain circumstances it needs to be 
+                           wrapped by a `char_()` parser component, though.
+                           Parsing of this component will succeed if the 
+                           single character has been matched.]]
+    [[explicit token id]  [To use an explicit token id in a __qi__ grammar you
+                           are required to wrap it with the special `token()` 
+                           parser component. Parsing of this component will 
+                           succeed if the current token has the same token
+                           id as specified in the expression `token(<id>)`.]]
+]
+
+The grammar definition below uses each of the three types demonstrating their
+usage.
+
+[wcp_grammar_definition]
+
+As already described (see: __sec_qi_karma_attributes__), the __qi__ parser 
+library builds upon a set of of fully attributed parser components. 
+Consequently, all the token definitions do support the this attribute model as
+well. The most natural way of implementing this was to use the token values as 
+the attributes exposed by the parser component corresponding to the token 
+definition (you can read more about this topic here: __sec_lex_tokenvalues__). 
+The example above takes advantage of the full integration of the token values 
+as the `token_def<>`'s parser attributes: the `word` token definition is 
+declared as a `token_def<std::string>`, making every instance of a `word` token
+carry the string representation of the matched input sequence as its value.
+The semantic action attached to `tok.word` receives this string (represented by 
+the `_1` placeholder) and uses it to calculate the number of matched
+characters: `ref(c) += size(_1)`.
+
+[important  All placeholders (`_1`, `_2`, etc.) used in /parser/ semantic 
+            actions in conjunction with functors created based on __phoenix2__ 
+            need to be imported from the `namespace boost::spirit::arg_names` 
+            (and *not* `namespace boost::phoenix::arg_names`, which is 
+            different from using placeholders in __lex__). 
+            Using the wrong placeholders leads to subtle compilation errors 
+            which are difficult to backtrack to their cause.
+]
+
+
+[heading Pulling Everything Together]
+
+The main function needs to implement a bit more logic now as we have to 
+initialize and start not only the lexical analysis but the parsing process as 
+well. The three type definitions (`typedef` statements) simplify the creation 
+of the lexical analyzer and the grammar. After reading the contents of the 
+given file into memory it calls the function __api_tokenize_and_parse__ to 
+initialize the lexical analysis and parsing processes.
+
+[wcp_main]
+
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_semantic_actions.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_semantic_actions.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Lexer Semantic Actions]
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_states.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_states.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,21 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Lexer States]
+
+
+[heading Controlling the Lexer State from Lexer Semantic Actions]
+
+
+[heading Controlling the Lexer State from Parser Semantic Actions]
+
+
+[heading Using a Lexer State for the Skip Parser]
+
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_static_model.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_static_model.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,119 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section The /Static/ Lexer Model]
+
+The documentation of __lex__ so far mostly was about describing the features of
+the /dynamic/ model, where the tables needed for lexical analysis are generated
+from the regular expressions at runtime. The big advantage of the dynamic model
+is its flexibility, and its integration with the __spirit__ library and the C++
+host language. Its big disadvantage is the need to spend additional runtime to 
+generate the tables, which especially might be a limitation for larger lexical 
+analyers. The /static/ model strives to build upon the smooth integration with
+__spirit__ and C++, and reuses large parts of the __lex__ library as described
+so far, while overcoming the additional runtime requirements by using 
+pre-generated tables and tokenizer routines. To make the code generation as 
+simple as possible, it is possible reuse the token definition types developed 
+using the /dynamic/ model without any changes. As will be shown in this 
+section, building a code generator based on an existing token definition type 
+is a matter of writing 3 lines of code.
+
+Assuming you already built a dynamic lexer for your problem, there are two more
+steps needed to create a static lexical analyzer using __lex__:
+
+# generating the C++ code for the static analyzer (including the tokenization 
+  function and corresponding tables), and 
+# modifying the dynamic lexical anlyzer to use the generated code.
+
+Both steps are described in more detail in the two sections below (for the full
+source code used in this example see the code here:
+[@../../example/lex/static_lexer/word_count_tokens.hpp the common token definition],
+[@../../example/lex/static_lexer/word_count_generate.cpp the code generator], 
+[@../../example/lex/static_lexer/word_count_static.hpp the generated code], and 
+[@../../example/lex/static_lexer/word_count_static.cpp the static lexical analyzer]).
+
+[import ../example/lex/static_lexer/word_count_tokens.hpp]
+[import ../example/lex/static_lexer/word_count_static.cpp]
+[import ../example/lex/static_lexer/word_count_generate.cpp]
+
+But first we provide the code snippets needed to understand the further 
+descriptions. Both, the definition of the used token identifier and the of the 
+token definition class in this example are put into a separate header file to 
+make these available to the code generator and the static lexical analyzer. 
+
+[wc_static_tokenids]
+
+The important point here is, that the token definition class is not different 
+from a similar class to be used for a dynamic lexical analyzer. The library 
+has been designed in a way, that all components (dynamic lexical analyzer, code 
+generator, and static lexical analyzer) can reuse the very same token definition 
+syntax.
+
+[wc_static_tokendef]
+
+The only thing changing between the three different use cases is the template
+parameter used to instantiate a concrete token definition. Fot the dynamic 
+model and the code generator you probably will use the __class_lexertl_lexer__
+template, where for the static model you will use the 
+__class_lexertl_static_lexer__ type as the template parameter.
+
+This example not only shows how to build a static lexer, but it additionally 
+demonstrates, how such a lexer can be used for parsing in conjunction with a 
+__qi__ grammar. For completeness we provide the simple grammar used in this 
+example. As you can see, this grammar does not have any dependencies on the 
+static lexical analyzer, and for this reason it is not different from a grammar
+used either without a lexer or using a dynamic lexical analyzer as described 
+before.
+
+[wc_static_grammar]
+
+
+[heading Generating the Static Analyzer]
+
+The first additional step to perform in order to create a static lexical 
+analyzer is to create a small standalone program for creating the lexer tables
+and the corresponding tokenization function. For this purpose the __lex__ 
+library exposes a special API - the function __api_generate_static__. It 
+implements the whole code generator, no further code is needed. All what it 
+takes to invoke this function is to supply a token definition instance, an 
+output stream to use to generate the code to, and an optional string to be used 
+as a prefix for the name of the generated function. All in all just a couple 
+lines of code.
+
+[wc_static_generate_main]
+
+The shown code generator will generate output, which should be stored in a file
+for later inclusion into the static lexical analzyer as shown in the next 
+topic (the full generated code can be viewed 
+[@../../example/lex/static_lexer/word_count_static.hpp here]).
+
+
+[heading Modifying the Dynamic Analyzer]
+
+The second required step to convert an existing dynamic lexer into a static one 
+is to change your main program at two places. First, you need to change the 
+type of the used lexer (that is the template parameter used while instantiating
+your token definition class). While in the dynamic model we have been using the
+__class_lexertl_lexer__ template, we now need to change that to the 
+__class_lexertl_static_lexer__ type. The second change is tightly related to 
+the first one and involves correcting the corresponding `#include` statement to:
+
+[wc_static_include]
+
+Otherwise the main program is not different from an equivalent program using 
+the dynamic model. This feature makes it really easy for instance to develop 
+the lexer in dynamic mode and to switch to the static mode after the code has
+been stabilized. The simple generator application showed above enables the 
+integration of the code generator into any existing build process. The 
+following code snippet provides the overall main function, highlighting 
+the code to be changed.
+
+[wc_static_main]
+
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/lexer_tutorials.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/lexer_tutorials.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,59 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section __lex__ Tutorials Overview]
+
+The __lex__ library implements several components on top of possibly different 
+lexer generator libraries. It exposes a pair of iterators, which, when 
+dereferenced, return a stream of tokens generated from the underlying character 
+stream. The generated tokens are based on the token definitions supplied by the 
+user.
+
+Currently, __lex__ is built on top of Ben Hansons excellent __lexertl__ 
+library (which is a proposed Boost library). __lexertl__ provides the necessary 
+functionality to build state 
+machines based on a set of supplied regular expressions. But __lex__ is not 
+restricted to be used with __lexertl__. We expect it to be usable in 
+conjunction with any other lexical scanner generator library, all what needs
+to be implemented is a set of wrapper objects exposing a well defined 
+interface as described in this documentation.
+
+[note   For the sake of clarity all examples in this documentation assume 
+        __lex__ to be used on top of __lexertl__.]
+
+Building a lexer using __lex__ is highly configurable, where most of this 
+configuration has to be done at compile time. Almost all of the configurable 
+parameters have generally useful default values, though, which means that 
+starting a project is easy and straightforward. Here is a (non-complete) list 
+of features you can tweak to adjust the generated lexer instance to the actual 
+needs:
+
+* Select and customize the token type to be generated by the lexer instance.
+* Select and customize the token value types the generated token instances will 
+  be able to hold.
+* Select the iterator type of the underlying input stream, which will be used 
+  as the source for the character stream to tokenize.
+* Customize the iterator type returned by the lexer to enable debug support,
+  special handling of certain input sequences, etc.
+* Select the /dynamic/ or the /static/ runtime model for the lexical
+  analyzer.
+
+Special care has been taken during the development of the library that 
+optimal code will be generated regardless of the configuration options 
+selected.
+
+The series of tutorial examples of this section will guide you through some
+common use cases helping to understand the big picture. The first two quick 
+start examples (__sec_lex_quickstart_1__ and __sec_lex_quickstart_2__) 
+introduce the __lex__ library while building two standalone applications, not
+being connected to or depending on any other part of __spirit__. The section
+__sec_lex_quickstart_3__ demonstrates how to use a lexer in conjunction with a 
+parser (where certainly the parser is built using __qi__). 
+
+[endsect]
+
Added: trunk/libs/spirit/doc/lex/parsing_using_a_lexer.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/parsing_using_a_lexer.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,15 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Parsing using a Lexer]
+
+[/ write about integration of lexer component with __qi__]
+
+[/ write about iterator interface exposed by a __lex__ lexer]
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/token_definition.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/token_definition.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,11 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Ways to define Tokens]
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/tokenizing.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/tokenizing.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,15 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Tokenizing Input Data]
+
+[heading The tokenize() function]
+
+[heading The generate_static() function]
+
+[endsect]
Added: trunk/libs/spirit/doc/lex/tokens_values.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/lex/tokens_values.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,207 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section About Tokens and Token Values]
+
+As already discussed, lexical scanning is the process of analyzing the stream 
+of input characters and separating it into strings called tokens, most of the 
+time separated by whitespace. The different token types recognized by a lexical 
+analyzer often get assigned unique integer token identifiers (token ids). These 
+token ids arenormally used by the parser to identifiy the current token without 
+having to look at the matched string again. The __lex__ library is not 
+different with respect to this, as it uses the token ids as the main means of 
+identification of the different token types defined for a particular lexical 
+analyzer. However, it is different from commonly used lexical analyzers in the 
+sense that it returns (references to) instances of a (user defined) token class 
+to the user. The only real limitation posed on this token class is consequently, 
+that it has to carry at least the token id of the token it represents. For more 
+information about the interface a user defined token type has to expose please 
+look at the __sec_ref_lex_token__ reference. The library provides a default 
+token type based on the __lexertl__ library which should be sufficient in most 
+use cases: the __class_lexertl_token__ type. This section focusses on the 
+description of general features a token class may implement and how this 
+integrates with the other parts of the __lex__ library.
+
+[heading The Anatomy of a Token]
+
+It is very important to understand the difference between a token definition 
+(represented by the __class_token_def__ template) and a token itself (for 
+instance represented by the __class_lexertl_token__ template). 
+
+The token definition is used to describe the main features of a particular 
+token type, especially:
+
+* to simplify the definition of a token type using a regular expression pattern 
+  applied while matching this token type,
+* to associate a token type with a particular lexer state,
+* to optionally assign a token id to a token type,
+* to optionally associate some code to execute whenever an instance of this 
+  token type has been matched,
+* and to optionally specify the attribute type of the token value.
+
+The token itself is a data structure returned by the lexer iterators. 
+Dereferencing a lexer iterator returns a reference to the last matched token 
+instance. It encapsulates the part of the underlying input sequence matched by
+the regular expression used during the definiton of this token type. 
+Incrementing the lexer iterator invokes the lexical analyzer to
+match the next token by advancing the underlying input stream. The token data 
+structure contains at least the token id of the matched token type, 
+allowing to identify the matched character sequence. Optionally, the token 
+instance may contain a token value and/or the lexer state this token instance
+was matched in. The following [link spirit.lex.tokenstructure figure] shows the 
+schematic structure of a token.
+
+[fig ./images/TokenStructure.png..The structure of a token..spirit.lex.tokenstructure]
+
+The token value and the token state may be omitted for optimization reasons, 
+avoiding the token to carry more data than actually required. This 
+configuration can be achieved by supplying appropriate template parameters 
+for the __class_lexertl_token__ template while defining the token type. 
+
+The lexer iterator returns the same token type for each of the different 
+matched token definitions. To accomodate for the possibly different token 
+/value/ types exposed by the various token types (token definitions), the 
+general type of the token value is a __boost_variant__. As a minimum (for the 
+default configuration) this token value variant will be configured to always 
+hold a __boost_iterator_range__ containing the pair of iterators pointing to 
+the matched input sequence for this token instance.
+
+[note If the lexical analyzer is used in conjunction with a __qi__ parser, the 
+      stored __boost_iterator_range__ token value will be converted to the 
+      requested token type (parser attribute) exactly once. This happens at the 
+      time of the first access to the token value requiring the  
+      corresponding type conversion. The converted token value will be stored 
+      in the __boost_variant__ replacing the initially stored iterator range.
+      This avoids to convert the input sequence to the token value more than 
+      once, thus optimizing the integration of the lexer with __qi__, even 
+      during parser backtracking.
+]
+
+Here is the template prototype of the __class_lexertl_token__ template:
+
+    template <
+        typename Iterator = char const*, 
+        typename AttributeTypes = mpl::vector0<>, 
+        typename HasState = mpl::true_
+    >
+    struct lexertl_token;
+
+[variablelist where:
+    [[Iterator]       [This is the type of the iterator used to access the 
+                       underlying input stream. It defaults to a plain 
+                       `char const*`.]]
+    [[AttributeTypes] [This is either a mpl sequence containing all 
+                       attribute types used for the token definitions or the
+                       type `omitted`. If the mpl sequence is empty (which is 
+                       the default), all token instances will store a 
+                       `boost::iterator_range<Iterator>` pointing to the start
+                       and the end of the matched section in the input stream.
+                       If the type is `omitted`, the generated tokens will
+                       contain no token value (attribute) at all.]]
+    [[HasState]       [This is either `mpl::true_` or `mpl::false_`, allowing
+                       to control whether the generated token instances will
+                       contain the lexer state they were generated in. The 
+                       default is mpl::true_, so all token instances will 
+                       contain the lexer state.]]
+]
+
+Normally, during its construction, a token instance always holds the 
+__boost_iterator_range__ as its token value (except, if it has been defined 
+using the `omitted` token value type). This iterator range then is 
+converted in place to the requested token value type (attribute) when it is
+requested for the first time.
+
+
+[heading The Physiognomy of a Token Definition]
+
+The token definitions (represented by the __class_token_def__ template) are 
+normally used as part of the definition of the lexical analyzer. At the same 
+time a token definition instance may be used as a parser component in __qi__.
+
+The template prototype of this class is shown here:
+
+    template<
+        typename Attribute = unused_type, 
+        typename Char = char
+    >
+    class token_def;
+
+[variablelist where:
+    [[Attribute]      [This is the type of the token value (attribute) 
+                       supported by token instances representing this token 
+                       type. This attribute type is exposed to the __qi__ 
+                       library, whenever this token definition is used as a 
+                       parser component. The default attribute type is 
+                       `unused_type`, which means the token instance holds a
+                       __boost_iterator_range__ pointing to the start
+                       and the end of the matched section in the input stream.
+                       If the attribute is `omitted` the token instance will
+                       expose no token type at all. Any other type will be 
+                       used directly as the token value type.]]
+    [[Char]           [This is the value type of the iterator for the 
+                       underlying input sequence. It defaults to `char`.]]
+]
+
+The semantics of the template parameters for the token type and the token 
+definition type are very similar and interdependent. As a rule of thumb you can 
+think of the token definition type as the means of specifying everything 
+related to a single specific token type (such as `identifier` or `integer`).
+On the other hand the token type is used to define the general proerties of all
+token instances generated by the __lex__ library.
+
+[important If you don't list any token value types in the token type definition 
+           declaration (resulting in the usage of the default __boost_iterator_range__ 
+           token type) everything will compile and work just fine, just a bit 
+           less efficient. This is because the token value will be converted 
+           from the matched input sequence every time it is requested. 
+           
+           But as soon as you specify at least one token value type while 
+           defining the token type you'll have to list all value types used for 
+           __class_token_def__ declarations in the token definition class, 
+           otherwise compilation errors will occur.
+]
+
+
+[heading Examples of using __class_lexertl_token__]
+
+Let's start with some examples. We refer to one of the __lex__ examples (for 
+the full source code of this example please see 
+[@../../example/lex/example4.cpp example4.cpp]).
+
+[import ../example/lex/example4.cpp]
+
+The first code snippet shows an excerpt of the token definition class, the
+definition of a couple of token types. Some of the token types do not expose a
+special token value (`if_`, `else_`, and `while_`). Their token value will
+always hold the iterator range of the matched input sequence only. The token
+definitions for the `identifier` and the integer `constant` are specialized 
+to expose an explicit token type each: `std::string` and `unsigned int`.
+
+[example4_token_def]
+
+As the parsers generated by __qi__ are fully attributed, any __qi__ parser 
+component needs to expose a certain type as its parser attribute. Naturally, 
+the __class_token_def__ exposes the token value type as its parser attribute, 
+enabling a smooth integration with __qi__.
+
+The next code snippet demonstrates how the required token value types are 
+specified while defining the token type to use. All of the token value types
+used for at least one of the token definitions have to be re-iterated for the 
+token definition as well.
+
+[example4_token]
+
+To avoid the token to have a token value at all, the special tag `omitted` can 
+be used: `token_def<omitted>` and `lexertl_token<base_iterator_type, omitted>`.
+
+
+
+
+
+
+[endsect]
Added: trunk/libs/spirit/doc/notes.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/notes.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,24 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Notes]
+
+[section Portability]
+[endsect]
+
+[section Porting from Spirit 1.8.x]
+[endsect]
+
+[section Style Guide]
+[include        notes/style_guide.qbk]
+[endsect]
+
+[section Techniques]
+[endsect]
+
+[endsect]
Added: trunk/libs/spirit/doc/notes/style_guide.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/notes/style_guide.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,87 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+At some point, especially when there are lots of semantic actions attached to
+various points, the grammar tends to be quite difficult to follow. In order to
+keep an easy-to-read, consistent en aesthetically pleasing look to the Spirit
+code, the following coding styleguide is advised.
+
+This coding style is adapted and extended from the ANTLR/PCCTS style (Terrence
+Parr) and [@http://groups.yahoo.com/group/boost/files/coding_guidelines.html
+Boost coding guidelines] (David Abrahams and Nathan Myers) and is the
+combined work of Joel de Guzman, Chris Uzdavinis and Hartmut Kaiser.
+
+* Rule names use std C++ (Boost) convention. The rule name may be very long.
+* The '=' is neatly indented 4 spaces below. Like in Boost, use spaces instead
+  of tabs.
+* Breaking the operands into separate lines puts the semantic actions neatly
+  to the right.
+* Semicolon at the last line terminates the rule.
+* The adjacent parts of a sequence should be indented accordingly to have all,
+  what belongs to one level, at one indentation level.
+
+    program
+        =   program_heading [heading_action]
+            >> block [block_action]
+            >> '.'
+        |   another_sequence
+            >> etc
+        ;
+
+* Prefer literals in the grammar instead of identifiers. e.g. `"program"` instead
+  of `PROGRAM`, `'>='` instead of `GTE` and `'.'` instead of `DOT`. This makes it much
+  easier to read. If this isn't possible (for instance where the used tokens
+  must be identified through integers) capitalized  identifiers should be used
+  instead.
+* Breaking the operands may not be needed for short expressions.
+  e.g. `*(',' >> file_identifier)` as long as the line does not
+  exceed 80   characters.
+* If a sequence fits on one line, put spaces inside the parentheses
+  to clearly separate them from the rules.
+
+    program_heading
+        =   no_case["program"]
+            >> identifier
+            >> '('
+            >> file_identifier
+            >> *( ',' >> file_identifier )
+            >> ')'
+            >> ';'
+        ;
+
+* Nesting directives: If a rule does not fit on one line (80 characters)
+  it should be continued on the next line intended by one level. The brackets
+  of directives, semantic expressions (using Phoenix or LL lambda expressions)
+  or parsers should be placed as follows.
+
+    identifier
+        =   no_case
+            [
+                lexeme
+                [
+                    alpha >> *(alnum | '_') [id_action]
+                ]
+            ]
+       ;
+
+* Nesting unary operators (e.g.Kleene star): Unary rule operators
+  (Kleene star, `'!'`, `'+'` etc.) should be moved out one space before
+  the corresponding indentation level, if this rule has a body or a
+  sequence after it, which does not fit on on line. This makes the
+  formatting more consistent and moves the rule 'body' at the same
+  indentation level as the rule itself, highlighting the unary operator.
+
+    block
+       =  *(   label_declaration_part
+           |   constant_definition_part
+           |   type_definition_part
+           |   variable_declaration_part
+           |   procedure_and_function_declaration_part
+           )
+           >> statement_part
+       ;
Added: trunk/libs/spirit/doc/outline.txt
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/outline.txt	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,97 @@
+# Copyright (C) 2001-2008 Joel de Guzman
+# Copyright (C) 2001-2008 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)
+
+
+Preface
+What's New
+Introduction
+Qi and Karma
+    Tutorials
+    Abstracts
+        Parsing Expression Grammar
+        Parsing and Generating
+        Primitives
+        Operators
+        Attributes
+        Semantic Actions
+        Directives
+        Rules
+        Grammars
+        Debugging
+        Error Handling
+        Parse Trees and ASTs
+    Quick Reference
+    Reference
+        Concepts
+            Parser
+            Generator
+            Parser Director
+            Generator Director
+        Char
+        String
+        Numeric
+        Binary
+        Directive
+        Action
+        Nonterminal
+        Operator
+        Stream
+        Auxiliary
+        Debug
+Lex
+    Introduction
+    Tutorials
+    Abstracts
+        Parsing using a Lexer
+        Lexer Primitives
+        Lexer States
+        Lexer Attributes
+        Lexer Semantic Actions
+    Quick Reference
+    Reference
+        Concepts
+            Lexer
+            Token 
+            TokenDef
+            TokenSet
+        Lexer Class
+        Token Class
+        TokenDef Class
+        TokenSet Class
+FAQ
+Notes
+    Portability
+    Porting from Spirit 1.8.x
+    Style Guide
+    Techniques
+Rationale
+Acknowledgments
+References
+
+-----------------------------------------------------------------
+
+Concepts Outline:
+    Description
+    Notation
+    Valid Expressions
+        Expression | Semantics | Return type | Complexity
+    Type Requirements
+        Expression | Requirements
+    Invariants
+    Models
+
+Reference Page Outline:
+    Description
+    Header
+    Synopsis
+    Template parameters
+    Model of
+    Objects
+    Expression Semantics
+        Expression | Semantics | Return type | Complexity
+    Example
+
+
Added: trunk/libs/spirit/doc/preface.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/preface.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,217 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Preface]
+
+[:['["Examples of designs that meet most of the criteria for
+"goodness" (easy to understand, flexible, efficient) are a recursive-
+descent parser, which is traditional procedural code. Another example
+is the STL, which is a generic library of containers and algorithms
+depending crucially on both traditional procedural code and on
+parametric polymorphism.]] [*--Bjarne Stroustrup]]
+
+[heading History]
+
+[heading /80s/]
+
+In the Mid 80s, Joel wrote his first calculator in Pascal. It has been
+an unforgettable coding experience. He was amazed how a mutually
+recursive set of functions can model a grammar specification. In time,
+the skills he acquired from that academic experience became very
+practical. Periodically Joel was tasked to do some parsing. For
+instance, whenever he needs to perform any form of I/O, even in
+binary, he tries to approach the task somewhat formally by writing a
+grammar using Pascal- like syntax diagrams and then write a
+corresponding recursive-descent parser. This worked very well.
+
+[heading /90s/]
+
+The arrival of the Internet and the World Wide Web magnified this
+thousand-fold. At one point Joel had to write an HTML parser for a Web
+browser project. He got a recursive-descent HTML parser working based
+on the W3C formal specifications easily. He was certainly glad that
+HTML had a formal grammar specification. Because of the influence of
+the Internet, Joel then had to do more parsing. RFC specifications
+were everywhere. SGML, HTML, XML, even email addresses and those
+seemingly trivial URLs were all formally specified using small EBNF-
+style grammar specifications. This made him wish for a tool similar to
+big- time parser generators such as YACC and ANTLR, where a parser is
+built automatically from a grammar specification. Yet, he wants it to
+be extremely small; small enough to fit in my pocket, yet scalable.
+
+It must be able to practically parse simple grammars such as email
+addresses to moderately complex grammars such as XML and perhaps some
+small to medium-sized scripting languages. Scalability is a prime
+goal. You should be able to use it for small tasks such as parsing
+command lines without incurring a heavy payload, as you do when you
+are using YACC or PCCTS. Even now that it has evolved and matured to
+become a multi-module library, true to its original intent, Spirit can
+still be used for extreme micro-parsing tasks. You only pay for
+features that you need. The power of Spirit comes from its modularity
+and extensibility. Instead of giving you a sledgehammer, it gives you
+the right ingredients to create a sledgehammer easily.
+
+The result was Spirit. Spirit was a personal project that was
+conceived when Joel was doing R&D in Japan. Inspired by the GoF's
+composite and interpreter patterns, he realized that he can model a
+recursive-descent parser with hierarchical-object composition of
+primitives (terminals) and composites (productions). The original
+version was implemented with run-time polymorphic classes. A parser is
+generated at run time by feeding in production rule strings such as:
+
+    "prod ::= {'A' | 'B'} 'C';"
+
+A compile function compiled the parser, dynamically creating a
+hierarchy of objects and linking semantic actions on the fly. A very
+early text can be found here: __early_spirit__.
+
+[heading /2001 to 2006/]
+
+Version 1.0 to 1.8 was a complete rewrite of the original Spirit
+parser using expression templates and static polymorphism, inspired by
+the works of Todd Veldhuizen (__todd__exprtemplates__, C++ Report,
+June 1995). Initially, the static-Spirit version was meant only to
+replace the core of the original dynamic-Spirit. Dynamic-spirit
+needed a parser to implement itself anyway. The original employed a
+hand-coded recursive-descent parser to parse the input grammar
+specification strings. Incidentially it was the time, when Hartmut
+joined the Spirit development.
+
+After its initial "open-source" debut in May 2001, static-Spirit
+became a success. At around November 2001, the Spirit website had an
+activity percentile of 98%, making it the number one parser tool at
+Source Forge at the time. Not bad for such a niche project such as a
+parser library. The "static" portion of Spirit was forgotten and
+static-Spirit simply became Spirit. The library soon evolved to
+acquire more dynamic features.
+
+Spirit was formally accepted into __boost__ in October 2002. Boost is
+a peer-reviewed, open collaborative development effort that is a
+collection of free Open Source C++ libraries covering a wide range of
+domains. The Boost Libraries have become widely known as an industry
+standard for design and implementation quality, robustness, and
+reusability.
+
+[heading /2007/]
+
+Over the years, especially after Spirit was accepted into Boost,
+Spirit has served its purpose quite admirably. The focus of what we'll
+now call [*/Classic-Spirit/] (versions prior to 2.0) was on
+transduction parsing where the input string is merely translated to an
+output string. A lot of parsers are of the transduction type. When the
+time came to add attributes to the parser library, it was done rather
+in an ad-hoc manner, with the goal being 100% backward compatible with
+classic Spirit. Some parsers have attributes, some don't.
+
+Spirit V2 is another major rewrite. Spirit V2 grammars are fully
+attributed (see __attr_grammar__). All parser components have
+attributes. To do this efficiently and ellegantly, we had to use a
+couple of infrastructure libraries. Some of which haven't been written
+yet at the time, some were quite new when Spirit debuted, and some
+needed work. __mpl__ is an important infrastructure library, yet is
+not sufficient to implement Spirit V2. Another library had to be
+written: __fusion__. Fusion sits between MPL and STL --between compile
+time and runtime -- mapping types to values. Fusion is a direct
+descendant of both MPL and __boost_tuples__ (Fusion is now a full
+fledged __boost__ library). __phoenix__ also had to be beefed up to
+support Spirit V2. The result is __phoenix2__. Last but not least,
+Spirit V2 uses an __todd__exprtemplates__ library called
+__boost_proto__.
+
+[heading New Ideas: Spirit V2]
+
+Just before the development of Spirit V2 began, Hartmut came across
+the __string_template__ library which is a part of the ANTLR parser
+framework. It is a Java template engine (with ports for C# and Python)
+for generating source code, web pages, emails, or any other formatted
+text output. With it, he got the the idea of using a formal notation
+(a grammar) to describe the expected structure of an input character
+sequence. The same grammar may be used to formalize the structure of a
+corresponding output character sequence. This is possible because
+parsing, most of the time, is implemented by comparing the input with
+the patterns defined by the grammar. If we use the same patterns to
+format a matching output, the generated sequence will follow the rules
+of the grammar as well.
+
+This insight lead to the implementation of a grammar driven output generation
+library compatibile with the Spirit parser library. As it turned out, parsing
+and generation are tightly connected and have very similar concepts. The
+duality of these two sides of the same medal is ubiquitous, which
+allowed us to build the parser library __qi__ and the generator library
+__karma__ using the same component infastructure.
+
+The idea of creating a lexer library well integrated with the Spirit parsers is
+not new. This has been discussed almost for the whole time of the existence of
+Classic-Spirit (pre V2) now. Several attempts to integrate existing lexer
+libraries and frameworks with Spirit have been made and served as a proof of
+concept and usability (for example see __wave__: The Boost C/C++ Preprocessor
+Library, and __slex__: a fully dynamic C++ lexer implemented with Spirit).
+Based on these experiences we added __lex__: a fully integrated lexer library
+to the mix, allowing to take advantage of the power of regular expressions for
+token matching, removing pressure from the parser components, simplifying
+parser grammars. Again, Spirit's modular structure allowed us to reuse the same
+underlying component library as for the parser and generator libraries.
+
+
+[heading How to use this manual]
+
+Each major section (there are two: __sec_qi_and_karma__, and __sec_lex__) is
+roughly divided into 3 parts:
+
+# Tutorials: A step by step guide with heavily annotated code. These
+  are meant to get the user acquainted with the library as quickly as
+  possible. The objective is to build the confidence of the user in
+  using the library using abundant examples and detailed instructions.
+  Examples speak volumes.
+
+# Abstracts: A high level summary of key topics. The objective is to
+  give the user a high level view of the library, the key concepts,
+  background and theories.
+
+# Reference: Detailed formal technical reference. We start with a quick
+  reference -- an easy to use table that maps into the reference proper.
+  The reference proper starts with C++ __cpp_concepts__ followed by
+  models of the concepts.
+
+Some icons are used to mark certain topics indicative of their relevance.
+These icons precede some text to indicate:
+
+[table Icons
+
+    [[Icon]             [Name]          [Meaning]]
+
+    [[__note__]         [Note]          [Generally useful information (an aside that
+                                        doesn't fit in the flow of the text)]]
+
+    [[__tip__]          [Tip]           [Suggestion on how to do something
+                                        (especially something that not be obvious)]]
+
+    [[__important__]    [Important]     [Important note on something to take
+                                        particular notice of]]
+
+    [[__caution__]      [Caution]       [Take special care with this - it may
+                                        not be what you expect and may cause bad
+                                        results]]
+
+    [[__danger__]       [Danger]        [This is likely to cause serious
+                                        trouble if ignored]]
+]
+
+This documentation is automatically generated by Boost QuickBook documentation
+tool. QuickBook can be found in the __boost_tools__.
+
+[heading Support]
+
+Please direct all questions to Spirit's mailing list. You can subscribe to the
+__spirit_list__. The mailing list has a searchable archive. A search link to
+this archive is provided in __spirit__'s home page. You may also read and post
+messages to the mailing list through __spirit_general__ (thanks to __gmane__).
+The news group mirrors the mailing list. Here is a link to the archives:
+__mlist_archive__.
+
+[endsect] [/ Preface]
Added: trunk/libs/spirit/doc/qi_and_karma.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,52 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Qi and Karma]
+
+[include    qi_and_karma/tutorials.qbk]
+
+[section    Abstracts]
+[include        qi_and_karma/peg.qbk]
+[include        qi_and_karma/parsing.qbk]
+[include        qi_and_karma/generating.qbk]
+[include        qi_and_karma/primitives.qbk]
+[include        qi_and_karma/operators.qbk]
+[include        qi_and_karma/attributes.qbk]
+[include        qi_and_karma/semantic_actions.qbk]
+[include        qi_and_karma/directives.qbk]
+[include        qi_and_karma/rules.qbk]
+[include        qi_and_karma/grammars.qbk]
+[include        qi_and_karma/debugging.qbk]
+[include        qi_and_karma/error_handling.qbk]
+[include        qi_and_karma/parse_trees_and_asts.qbk]
+[endsect]
+
+[/section    Quick Reference]
+[include        qi_and_karma/quick_reference.qbk]
+[/endsect]
+
+[section    Reference]
+[section        Concepts]
+[include            reference/qi_and_karma/parser.qbk]
+[include            reference/qi_and_karma/generator.qbk]
+[endsect]
+[include        reference/qi_and_karma/char.qbk]
+[include        reference/qi_and_karma/string.qbk]
+[include        reference/qi_and_karma/numeric.qbk]
+[include        reference/qi_and_karma/binary.qbk]
+[include        reference/qi_and_karma/directive.qbk]
+[include        reference/qi_and_karma/action.qbk]
+[include        reference/qi_and_karma/nonterminal.qbk]
+[include        reference/qi_and_karma/operator.qbk]
+[include        reference/qi_and_karma/stream.qbk]
+[include        reference/qi_and_karma/auxiliary.qbk]
+[include        reference/qi_and_karma/debug.qbk]
+[endsect]
+
+[endsect]
+
Added: trunk/libs/spirit/doc/qi_and_karma/attributes.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/attributes.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Attributes]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/debugging.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/debugging.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Debugging]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/directives.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/directives.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Directives]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/error_handling.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/error_handling.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Error Handling]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/generating.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/generating.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,24 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Parsing and Generating]
+
+[heading The API functions exposed by __qi__ ]
+
+[heading The parse() function]
+
+[heading The phrase_parse() function]
+
+[heading The tokenize_and_parse() function]
+
+[heading The tokenize_and_phrase_parse() function]
+
+[heading The make_parser() function]
+
+[endsect]
+
Added: trunk/libs/spirit/doc/qi_and_karma/grammars.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/grammars.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Grammars]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/operators.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/operators.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Operators]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/parse_trees_and_asts.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/parse_trees_and_asts.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Parse Trees and ASTs]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/parsing.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/parsing.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,44 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Parsing]
+
+Central to the library is the parser. The parser does the actual
+work of recognizing a linear input stream of data read sequentially
+from start to end by the supplied iterators. The parser attempts to
+match the input following a well-defined set of specifications known
+as grammar rules. The parser returns a `bool` to report the success or
+failure. When successful, the parser calls a client-supplied semantic
+action, if there is one. The semantic action extracts structural
+information depending on the data passed by the parser and the
+hierarchical context of the parser it is attached to.
+
+Parsers come in different flavors. The Spirit library comes bundled with an extensive set of pre-defined parsers that perform various parsing tasks from the trivial to the complex. The parser, as a concept, has a public conceptual interface contract. Following the contract, anyone can write a conforming parser that will play along well with the library's predefined components. We shall provide a blueprint detailing the conceptual interface of the parser later.
+
+Clients of the library generally do not need to write their own hand-coded parsers at all. Spirit has an immense repertoire of pre-defined parsers covering all aspects of syntax and semantic analysis. We shall examine this repertoire of parsers in the following sections. In the rare case where a specific functionality is not available, it is extremely easy to write a user-defined parser. The ease in writing a parser entity is the main reason for Spirit's extensibility.
+
+
+
+
+
+
+
+[heading The API functions exposed by __qi__ ]
+
+[heading The parse() function]
+
+[heading The phrase_parse() function]
+
+[heading The tokenize_and_parse() function]
+
+[heading The tokenize_and_phrase_parse() function]
+
+[heading The make_parser() function]
+
+[endsect]
+
Added: trunk/libs/spirit/doc/qi_and_karma/peg.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/peg.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Parsing Expression Grammar]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/primitives.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/primitives.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Primitives]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/quick_reference.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/quick_reference.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,43 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Quick Reference]
+
+The following tables use some conventions to encode the attribute type exposed
+by a component
+
+[variablelist
+    [[`attribute_of(P)`]    [The component exposes the same attribute as the 
+                             component 'P' used as part of the overall 
+                             construct]]
+    [[`value_type(I)`]      [The component exposes the value_type of the 
+                             underlying iterator 'I' as its attribute type]]
+]
+
+[table Character Parsers
+    [[Component]  [Description]                     [Attribute]]
+    [[`char_`]      []      [`char`]]
+    [[`wchar`]      []      [`wchar_t`]]
+    [[`lit`]        []      [`unused`]]
+    [[`wlit`]       []      [`unused`]]
+    [[`'x'`]        []      [`unused`]]
+    [[`L'x'`]       []      [`unused`]]
+    [[`alnum`]      []      [`Char`]]
+    [[`alpha`]      []      [`Char`]]
+    [[`blank`]      []      [`Char`]]
+    [[`cntrl`]      []      [`Char`]]
+    [[`digit`]      []      [`Char`]]
+    [[`graph`]      []      [`Char`]]
+    [[`print`]      []      [`Char`]]
+    [[`punct`]      []      [`Char`]]
+    [[`space`]      []      [`Char`]]
+    [[`xdigit`]     []      [`Char`]]
+    [[`~P`]         []      [`attribute_of(P)`]]
+]
+
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/rules.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/rules.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Rules]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/semantic_actions.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/semantic_actions.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Semantic Actions]
+[endsect]
Added: trunk/libs/spirit/doc/qi_and_karma/tutorials.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/qi_and_karma/tutorials.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Tutorials]
+[endsect]
Added: trunk/libs/spirit/doc/rationale.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/rationale.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Rationale]
+[endsect]
Added: trunk/libs/spirit/doc/reference/lex/lexer.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/lex/lexer.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Lexer]
+[endsect]
Added: trunk/libs/spirit/doc/reference/lex/lexer_class.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/lex/lexer_class.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,19 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Lexer Class]
+
+[heading The lexertl_lexer Class Implementing the Dynamic Model]
+
+[heading The lexertl_actor_lexer Class Implementing the Dynamic Model]
+
+[heading The lexertl_static_lexer Class Implementing the Static Model]
+
+[heading The lexertl_static_actor_lexer Class Implementing the Static Model]
+
+[endsect]
Added: trunk/libs/spirit/doc/reference/lex/token.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/lex/token.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Token]
+[endsect]
Added: trunk/libs/spirit/doc/reference/lex/token_class.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/lex/token_class.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Token Class]
+[endsect]
Added: trunk/libs/spirit/doc/reference/lex/tokendef.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/lex/tokendef.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section TokenDef]
+[endsect]
Added: trunk/libs/spirit/doc/reference/lex/tokendef_class.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/lex/tokendef_class.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section TokenDef Class]
+[endsect]
Added: trunk/libs/spirit/doc/reference/lex/tokenset.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/lex/tokenset.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section TokenSet]
+[endsect]
Added: trunk/libs/spirit/doc/reference/lex/tokenset_class.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/lex/tokenset_class.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section TokenSet Class]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/action.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/action.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Action]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/auxiliary.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/auxiliary.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Auxiliary]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/binary.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/binary.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Binary]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/char.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/char.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Char]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/debug.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/debug.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Debug]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/directive.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/directive.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Directive]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/generator.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/generator.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Generator]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/nonterminal.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/nonterminal.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Nonterminal]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/numeric.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/numeric.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Numeric]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/operator.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/operator.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Operators]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/parser.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/parser.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,43 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Parser]
+
+[heading Description]
+
+Description of Parser concept
+
+[variablelist Notation
+    [[`p`]     [A Parser]]
+]
+
+[heading Valid Expressions]
+
+For any Parser the following expressions must be valid:
+
+[table
+    [[Expression]       [Semantics]             [Return type]       [Complexity]]
+    [[`xxx`]            [Semantics of `xxx`]    [Parser]            [Constant]]
+]
+
+[heading Type Requirements]
+
+[table
+    [[Expression]       [Requirements]]
+    [[`xxx`]            [Requirements for `xxx`]]
+]
+
+[heading Invariants]
+
+For any Parser xxx the following invariants always hold:
+
+[heading Models]
+
+Links to models of Parser concept
+
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/stream.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/stream.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section Stream]
+[endsect]
Added: trunk/libs/spirit/doc/reference/qi_and_karma/string.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/reference/qi_and_karma/string.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section String]
+[endsect]
Added: trunk/libs/spirit/doc/references.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/references.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,91 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section References]
+
+[table
+[[ ]   [Authors]                    [Title, Publisher/link, Date Published]]
+[[1.]  [Todd Veldhuizen]            [[@http://www.extreme.indiana.edu/%7Etveldhui/papers/Expression-Templates/exprtmpl.html
+                                    "Expression Templates"]. C++ Report, June 1995.]]
+[[2.]  [Peter Naur (ed.)]           [[@http://www.masswerk.at/algol60/report.htm
+                                    "Report on the Algorithmic Language ALGOL 60"]. CACM, May 1960.]]
+[[3.]  [ISO/IEC]                    [[@http://www.cl.cam.ac.uk/%7Emgk25/iso-14977.pdf "ISO-EBNF"],
+                                     ISO/IEC 14977: 1996(E).]]
+[[4.]  [Richard J.Botting, Ph.D.]   [[@http://www.csci.csusb.edu/dick/maths/intro_ebnf.html
+                                    "XBNF"] (citing Leu-Weiner, 1973).
+                                    California State University, San Bernardino, 1998.]]
+[[5.]  [James Coplien.]             ["Curiously Recurring Template Pattern".
+                                    C++ Report, Feb. 1995.]]
+[[6.]  [Thierry Geraud and
+       Alexandre Duret-Lutz]        [[@http://www.coldewey.com/europlop2000/papers/geraud%2Bduret.zip
+                                    Generic Programming Redesign of Patterns]
+                                    Proceedings of the 5th European Conference on Pattern Languages
+                                    of Programs(EuroPLoP'2000) Irsee, Germany, July 2000.]]
+[[7.]  [Geoffrey Furnish]           [[@http://www.adtmag.com/joop/carticle.aspx?ID=627
+                                    "Disambiguated Glommable Expression Templates Reintroduced"]
+                                    C++ Report, May 2000]]
+[[8.]  [Erich Gamma,
+        Richard Helm,
+        Ralph Jhonson,
+        and John Vlissides]         [Design Patterns, Elements of Reusable Object-Oriented Software.
+                                    Addison-Wesley, 1995.]]
+[[9.]  [Alfred V. Aho,
+        Revi Sethi,
+        Feffrey D. Ulman]           [Compilers, Principles, Techniques and Tools
+                                    Addison-Wesley, June 1987.]]
+[[10.] [Dick Grune and
+        Ceriel Jacobs]              [[@http://www.cs.vu.nl/%7Edick/PTAPG.html
+                                    Parsing Techniques: A Practical Guide.]
+                                    Ellis Horwood Ltd.: West Sussex, England, 1990.
+                                    (electronic copy, 1998).]]
+[[11.] [T. J. Parr,
+        H. G. Dietz, and
+        W. E. Cohen]                [[@http://citeseer.ist.psu.edu/6885.html
+                                    PCCTS Reference Manual (Version 1.00)].
+                                    School of Electrical Engineering, Purdue University,
+                                    West Lafayette, August 1991.]]
+[[12.] [Adrian Johnstone and
+        Elizabeth Scott.]           [[@ftp://ftp.cs.rhul.ac.uk/pub/rdp
+                                    RDP, A Recursive Descent Compiler Compiler].
+                                    Technical Report CSD TR 97 25, Dept. of Computer Science,
+                                    Egham, Surrey, England, Dec. 20, 1997.]]
+[[13.] [Adrian Johnstone]           [[@http://www.cs.rhul.ac.uk/research/languages/projects/lookahead_backtrack.shtml
+                                    Languages and Architectures,
+                                    Parser generators with backtrack or extended lookahead capability]
+                                    Department of Computer Science, Royal Holloway, University of London,
+                                    Egham, Surrey, England]]
+[[14.] [Damian Conway]              [[@http://www.csse.monash.edu.au/%7Edamian/papers/#Embedded_Input_Parsing_for_C
+                                    Parsing with C++ Classes].
+                                    ACM SIGPLAN Notices, 29:1, 1994.]]
+[[15.] [Joel de Guzman]             [[@http://spirit.sourceforge.net/distrib/spirit_1_8_5/libs/spirit/index.html
+                                    "Spirit Version 1.8"], 1998-2003.]]
+[[16.] [S. Doaitse Swierstra and
+        Luc Duponcheel]             [[@http://citeseer.ist.psu.edu/448665.html
+                                    Deterministic, Error-Correcting Combinator Parsers]
+                                    Dept. of Computer Science, Utrecht University P.O.Box 80.089,
+                                     3508 TB Utrecht, The Netherland]]
+[[17.] [Bjarne Stroustrup]          [[@http://www.research.att.com/%7Ebs/whitespace98.pdf
+                                    Generalizing Overloading for C++2000]
+                                    Overload, Issue 25. April 1, 1998.]]
+[[18.] [Dr. John Maddock]           [[@http://www.boost.org/libs/regex/index.html
+                                    Regex++ Documentation]
+                                    http://www.boost.org/libs/regex/index.htm]]
+[[19.] [Anonymous
+        Edited by Graham Hutton]    [[@http://www.cs.nott.ac.uk/~gmh//faq.html
+                                    Frequently Asked Questions for comp.lang.functional].
+                                    Edited by Graham Hutton, University of Nottingham.]]
+[[20.] [Hewlett-Packard]            [[@http://www.sgi.com/tech/stl/
+                                    Standard Template Library Programmer's Guide.], Hewlett-Packard Company, 1994]]
+[[21.] [Boost Libraries]            [[@http://boost.org/libs/libraries.htm
+                                    Boost Libraries Documentation].]]
+[[22.] [Brian McNamara and
+        Yannis Smaragdakis]         [[@http://www.cc.gatech.edu/~yannis/fc++/ FC++:Functional Programming in C++].]]
+[[23.] [Todd Veldhuizen]            [[@ftp://ftp.cs.indiana.edu/pub/techreports/TR542.pdf Techniques for Scientic C++.]]]
+]
+
+[endsect]
Added: trunk/libs/spirit/doc/spirit2.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/spirit2.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,143 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[article Spirit
+    [quickbook 1.4]
+    [version 2.0]
+    [authors [de Guzman, Joel], [Kaiser, Hartmut]]
+    [copyright 2001 2002 2003 2004 2005 2006 2007 2008 Joel de Guzman, Hartmut Kaiser]
+    [purpose Parser and Generator Library]
+    [license
+        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])
+    ]
+]
+
+[/ November 14, 2007 ]
+
+[/ Some links ]
+
+[def __spirit__                 [@http://spirit.sourceforge.net Spirit]]
+[def __phoenix__                [@http://boost.org/libs/spirit/phoenix/index.html Phoenix]]
+[def __phoenix2__               [@http://spirit.sourceforge.net/dl_more/phoenix_v2/libs/spirit/phoenix/doc/html/index.html Phoenix2]]
+[def __fusion__                 [@http://spirit.sourceforge.net/dl_more/fusion_v2/libs/fusion/doc/html/index.html Fusion]]
+[def __mpl__                    [@http://www.boost.org/libs/mpl/index.html MPL]]
+[def __boost_tuples__           [@http://www.boost.org/libs/tuple/index.html Boost.Tuples]]
+[def __boost_proto__            -Boost.Proto-]
+[def __boost__                  [@http://www.boost.org/ Boost]]
+[def __boost_tools__            [@http://www.boost.org/tools/index.html Boost Tools]]
+[def __spirit_list__            [@https://lists.sourceforge.net/lists/listinfo/spirit-general Spirit Mailing List]]
+[def __spirit_general__         [@news://news.gmane.org/gmane.comp.spirit.general Spirit General NNTP news portal]]
+[def __gmane__                  [@http://www.gmane.org Gmane]]
+[def __mlist_archive__          [@http://news.gmane.org/gmane.comp.parsers.spirit.general]]
+
+[def __early_spirit__           [@http://spirit.sourceforge.net/dl_docs/pre-spirit.htm pre-Spirit]]
+[def __todd__exprtemplates__    [@http://ubiety.uwaterloo.ca/~tveldhui/papers/Expression-Templates/exprtmpl.html Expression Templates]]
+[def __cpp_concepts__           [@http://en.wikipedia.org/wiki/C%2B%2B0x#Concept Concepts]]
+[def __attr_grammar__           [@http://en.wikipedia.org/wiki/Attribute_grammar Attribute Grammar]]
+[def __string_template__        [@http://www.stringtemplate.org/ StringTemplate]]
+[def __lexertl__                [@http://www.benhanson.net/lexertl.html Lexertl]]
+[def __wave__                   [@http://www.boost.org/libs/wave/index.html Wave]]
+[def __slex__                   [@http://spirit.sourceforge.net/repository/applications/slex.zip SLex]]
+[def __flex__                   [@http://flex.sourceforge.net/ Flex]]
+[def __re2c__                   [@http://re2c.sourceforge.net/ re2c]]
+[def __ragel__                  [@http://www.cs.queensu.ca/~thurston/ragel/ Ragel]]
+
+[def __boost_variant__          [@http://www.boost.org/doc/html/variant.html `boost::variant<>`]]
+[def __boost_iterator_range__   [@http://www.boost.org/libs/range/doc/utility_class.html#iter_range `boost::iterator_range<>`]]
+
+
+[def __qi__                     /Spirit.Qi/]
+[def __karma__                  /Spirit.Karma/]
+[def __lex__                    /Spirit.Lex/]
+
+
+[def __fixme__                  *FIXME*]
+
+
+[/ Sections ]
+
+[def __sec_qi_and_karma__       [link spirit.qi_and_karma Qi and Karma]]
+[def __sec_qi_karma_attributes__  [link spirit.qi_and_karma.abstracts.attributes Attributes]]
+
+[def __sec_lex__                [link spirit.__lex__ Lex]]
+[def __sec_lex_quickstart_1__   [link spirit.__lex__.__lex___tutorials.quickstart_1___a_word_counter_using___lex__ Lex Quickstart 1 - A word counter using __lex__]]
+[def __sec_lex_quickstart_2__   [link spirit.__lex__.__lex___tutorials.quickstart_2___a_better_word_counter_using___lex__ Lex Quickstart 2 - A better word counter using __lex__]]
+[def __sec_lex_quickstart_3__   [link spirit.__lex__.__lex___tutorials.quickstart_3___counting_words_using_a_parser Lex Quickstart 3 - Counting Words Using a Parser]]
+
+[def __sec_lex_static_model__   [link spirit.__lex__.abstracts.the__static__lexer_model The /Static/ Model]]
+[def __sec_lex_primitives__     [link spirit.__lex__.abstracts.lexer_primitives Lexer Primitives]]
+[def __sec_lex_tokenvalues__    [link spirit.__lex__.abstracts.lexer_primitives.about_tokens_and_token_values About Tokens and Token Values]]
+[def __sec_lex_attributes__     [link spirit.__lex__.abstracts.lexer_attributes Lexer Attributes]]
+
+[def __sec_ref_lex_token__      [link spirit.__lex__.reference.concepts.token Token Reference]]
+[def __sec_ref_lex_token_def__  [link spirit.__lex__.reference.concepts.tokendef TokenDef Reference]]
+
+[/ References to API descriptions ]
+
+[def __api_tokenize_and_parse__ [link spirit.qi_and_karma.abstracts.parsing_and_generating.the_tokenize_and_phrase_parse___function `tokenize_and_parse()`]]
+[def __api_generate_static__    [link spirit.__lex__.abstracts.tokenizing_input_data.the_generate_static___function `generate_static()`]]
+
+
+[/ References to classes ]
+
+[def __class_token_def__        [link spirit.__lex__.reference.tokendef_class `token_def<>`]]
+
+[def __class_lexertl_token__    [link spirit.__lex__.reference.token_class `lexertl_token<>`]]
+[def __class_lexertl_lexer__    [link spirit.__lex__.reference.lexer_class.the_lexertl_lexer_class_implementing_the_dynamic_model `lexertl_lexer<>`]]
+[def __class_lexertl_static_lexer__ [link spirit.__lex__.reference.lexer_class.the_lexertl_static_lexer_class_implementing_the_static_model `lexertl_static_lexer<>`]]
+
+
+[/ Some images ]
+
+[def __note__                   [$../../../../doc/html/images/adm_note.png]]
+[def __tip__                    [$../../../../doc/html/images/adm_tip.png]]
+[def __important__              [$../../../../doc/html/images/adm_important.png]]
+[def __caution__                [$../../../../doc/html/images/adm_caution.png]]
+[def __danger__                 [$../../../../doc/html/images/adm_danger.png]]
+
+
+[/ some templates]
+
+[/  fig[ref title label] 
+    Image element with a title. 
+
+    ref   := Reference to the image file. 
+    title := The title to associate with this figure. 
+    label := the id to use to be able to reference this picture
+] 
+[template fig[ref title label]'''
+    <figure id="'''[label]'''">
+        <title>'''[title]'''</title>
+        <inlinemediaobject>
+            <imageobject>
+                <imagedata fileref="'''[ref]'''"></imagedata>
+            </imageobject>
+            <textobject>
+                <phrase role="alt">'''[title]'''</phrase>
+            </textobject>
+        </inlinemediaobject>
+    </figure>
+'''] 
+
+
+[/ Here we go ]
+
+[include preface.qbk]
+[include what_s_new.qbk]
+[include introduction.qbk]
+[include qi_and_karma.qbk]
+[include lex.qbk]
+[include faq.qbk]
+[include notes.qbk]
+[include rationale.qbk]
+[include acknowledgments.qbk]
+[include references.qbk]
+
+
Added: trunk/libs/spirit/doc/what_s_new.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/doc/what_s_new.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+[/==============================================================================
+    Copyright (C) 2001-2008 Joel de Guzman
+    Copyright (C) 2001-2008 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)
+===============================================================================/]
+
+[section What's New]
+[endsect]
Added: trunk/libs/spirit/example/karma/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/Jamfile	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,12 @@
+#==============================================================================
+#   Copyright (c) 2001-2007 Joel de Guzman
+#   Copyright (c) 2001-2007 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)
+#==============================================================================
+project spirit-karma-example ;
+
+exe basic_facilities : basic_facilities.cpp ;
+exe functor_facilities : functor_facilities.cpp ;
+
Added: trunk/libs/spirit/example/karma/basic_facilities.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/basic_facilities.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,178 @@
+//  Copyright (c) 2001-2008 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 the uniform and easy way of
+//  output formatting for different container types. 
+//
+//  Since the 'stream' primitive used below uses the streaming operator defined 
+//  for the container value_type, you must make sure to have a corresponding
+//  operator<<() available for this contained data type. OTOH this means, that
+//  the format descriptions used below will be usable for any contained type as
+//  long as this type has an associated streaming operator defined.
+
+//  use a larger value for the alignment field width (default is 10)
+#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 25
+
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_stream.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <cstdlib> 
+
+#include <boost/range.hpp>
+#include <boost/date_time//gregorian/gregorian.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+namespace karma = boost::spirit::karma;
+
+///////////////////////////////////////////////////////////////////////////////
+// Output the given containers in list format
+// Note: the format description does not depend on the type of the sequence
+//       nor does it depend on the type of the elements contained in the 
+//       sequence
+///////////////////////////////////////////////////////////////////////////////
+template <typename Container>
+void output_container(std::ostream& os, Container const& c)
+{
+    // output the container as a space separated sequence
+    os << 
+        karma::format_delimited(
+            *stream,                              // format description
+            c,                                    // data
+            space                                 // delimiter
+        ) << std::endl << std::endl;
+
+    os << 
+        karma::format_delimited(
+            '[' << *stream << ']',                // format description
+            c,                                    // data
+            space                                 // delimiter
+        ) << std::endl << std::endl;
+
+    // output the container as a comma separated list
+    os << 
+        karma::format(
+            stream % ", ",                        // format description
+            c                                     // data
+        ) << std::endl << std::endl;
+
+    os << 
+        karma::format(
+            '[' << (stream % ", ") << ']',        // format description
+            c                                     // data
+        ) << std::endl << std::endl;
+
+    // output the container as a comma separated list of items enclosed in '()'
+    os << 
+        karma::format(
+            ('(' << stream << ')') % ", ",        // format description
+            c                                     // data
+        ) << std::endl << std::endl;
+
+    os << 
+        karma::format(
+            '[' << (  
+                ('(' << stream << ')') % ", "
+             )  << ']',                           // format description
+            c                                     // data
+        ) << std::endl << std::endl;
+        
+    // output the container as a HTML list
+    os << 
+        karma::format_delimited(
+            "<ol>" << 
+                *verbatim["<li>" << stream << "</li>"]
+            << "</ol>",                           // format description
+            c,                                    // data
+            '\n'                                  // delimiter
+        ) << std::endl;
+
+    // output the container as right aligned column
+    os << 
+        karma::format_delimited(
+           *verbatim[
+                "|" << right_align[stream] << "|"
+            ],                                    // format description
+            c,                                    // data
+            '\n'                                  // delimiter
+        ) << std::endl;
+
+    os << std::endl;
+}
+
+int main()
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // vector
+    std::vector<int> v (8);
+    std::generate(v.begin(), v.end(), std::rand); // randomly fill the vector
+
+    std::cout << "-------------------------------------------------------------" 
+              << std::endl;
+    std::cout << "std::vector<int>" << std::endl;
+    output_container(std::cout, v);
+        
+    ///////////////////////////////////////////////////////////////////////////
+    // list
+    std::list<char> l;
+    l.push_back('A');
+    l.push_back('B');
+    l.push_back('C');
+
+    std::cout << "-------------------------------------------------------------" 
+              << std::endl;
+    std::cout << "std::list<char>" << std::endl;
+    output_container(std::cout, l);
+
+    ///////////////////////////////////////////////////////////////////////////
+    // C-style array
+    int i[4] = { 3, 6, 9, 12 };
+    
+    std::cout << "-------------------------------------------------------------" 
+              << std::endl;
+    std::cout << "int i[]" << std::endl;
+    output_container(std::cout, boost::make_iterator_range(i, i+4));
+    
+    ///////////////////////////////////////////////////////////////////////////
+    // strings
+    std::string str("Hello world!");
+
+    std::cout << "-------------------------------------------------------------" 
+              << std::endl;
+    std::cout << "std::string" << std::endl;
+    output_container(std::cout, str);
+        
+    ///////////////////////////////////////////////////////////////////////////
+    //  vector of boost::date objects
+    //  Note: any registered facets get used!
+    using namespace boost::gregorian;
+    std::vector<date> dates;
+    dates.push_back(date(2005, Jun, 25));
+    dates.push_back(date(2006, Jan, 13));
+    dates.push_back(date(2007, May, 03));
+
+    date_facet* facet(new date_facet("%A %B %d, %Y"));
+    std::cout.imbue(std::locale(std::cout.getloc(), facet));
+
+    std::cout << "-------------------------------------------------------------" 
+              << std::endl;
+    std::cout << "std::vector<boost::date>" << std::endl;
+    output_container(std::cout, dates);
+    
+    ///////////////////////////////////////////////////////////////////////////
+    // fusion tuples
+    // this will work in the future
+//     boost::fusion::vector<int, char, double> fv(42, 'a', 45.8);
+//
+//     std::cout << "boost::fusion::vector<int, char, double>" << std::endl;
+//     output_container(std::cout, fv);
+    return 0;
+}
+
Added: trunk/libs/spirit/example/karma/functor_facilities.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/functor_facilities.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,202 @@
+//  Copyright (c) 2001-2008 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 examples demonstrate how to write functor based generators for special
+//  purposes. 
+
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_stream.hpp>
+
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_bind.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <cstdlib> 
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+//  The functor generator 'counter' can be used for output annotation with some
+//  item counting information.
+///////////////////////////////////////////////////////////////////////////////
+struct counter_impl : boost::spirit::karma::functor_base
+{
+    template <typename OutputIterator, typename Context, typename Parameter>
+    bool operator()(Parameter const&, Context& ctx, OutputIterator& sink) const
+    {
+        namespace karma = boost::spirit::karma;
+        return karma::generate(sink, int_ << ": ", counter++);
+    }
+    
+    counter_impl(int& counter_) 
+    : counter(counter_) {}
+    
+    int& counter;
+};
+
+inline boost::spirit::result_of::as_generator<counter_impl>::type
+counter(int& counter_)
+{
+    using namespace boost::spirit::karma;
+    return as_generator(counter_impl(counter_));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  The functor generator 'confix' allows a simple syntax for generating 
+//  output wrapped inside a pair of a prefix and a suffix.
+///////////////////////////////////////////////////////////////////////////////
+template <typename Expr>
+struct confix_impl : public boost::spirit::karma::functor_base
+{
+    template <typename Context>
+    struct apply
+    {
+        typedef boost::spirit::hold_any type;
+    };
+
+    template <typename OutputIterator, typename Context, typename Parameter>
+    bool operator()(Parameter const& v, Context& ctx, OutputIterator& sink) const
+    {
+        namespace karma = boost::spirit::karma;
+        return karma::generate(sink, open << xpr << close, v);
+    }
+    
+    confix_impl(char const* open_, char const* close_, Expr const& xpr_) 
+    : open(open_), close(close_), xpr(xpr_) {}
+    
+    std::string open;
+    std::string close;
+    Expr xpr;
+};
+
+template <typename Expr>
+inline typename boost::spirit::result_of::as_generator<confix_impl<Expr> >::type
+confix(Expr const& xpr_, char const* open_ = "", char const* close_ = "")
+{
+    using namespace boost::spirit::karma;
+    return as_generator(confix_impl<Expr>(open_, close_, xpr_));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  The functor generator 'list' allows a simple syntax for generating 
+//  list formatted output.
+//
+//  This example uses phoenix::bind to allow to omit the second argument from 
+//  the operator() and to allow to switch the remaining two arguments.
+///////////////////////////////////////////////////////////////////////////////
+template <typename Expr>
+struct list_impl : boost::spirit::karma::functor_base
+{
+    // this function will be called to generate the output
+    template <typename OutputIterator, typename Parameter>
+    bool operator()(OutputIterator& sink, Parameter const& v) const
+    {
+        namespace karma = boost::spirit::karma;
+        return karma::generate(sink, xpr % delim, v);
+    }
+    
+    list_impl(Expr const& xpr_, char const* delim_) 
+    : xpr(xpr_), delim(delim_) {}
+    
+    Expr xpr;
+    std::string delim;
+};
+
+//  Supply the expected parameter type explicitly
+struct list_impl_mf
+{
+    // the expected parameter type of a functor has to be defined using a
+    // embedded apply metafunction
+    template <typename Context>
+    struct apply
+    {
+        typedef boost::spirit::hold_any type;
+    };
+};
+
+template <typename Expr>
+inline list_impl<Expr>
+list(Expr const& xpr, char const* delim)
+{
+    return list_impl<Expr>(xpr, delim);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    namespace karma = boost::spirit::karma;
+    using namespace boost::phoenix;
+    using namespace boost::phoenix::arg_names;
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  Output the given containers in list format
+    //  We use a special functor generator here to annotate the output with 
+    //  a integer counting the entries.
+    ///////////////////////////////////////////////////////////////////////////
+    std::vector<int> v (8);
+    std::generate(v.begin(), v.end(), std::rand); // randomly fill the vector
+
+    int counter1 = 1;
+    std::cout << 
+        karma::format(
+            (counter(counter1) << int_) % ", ",   // format description
+            v                                     // data
+        ) << std::endl;
+
+    //  Here we initialize the counter to 100
+    int counter2 = 100;
+    std::cout << 
+        karma::format(
+            '[' << (
+                (counter(counter2) << int_) % ", "
+             ) << ']',                            // format description
+            v                                     // data
+        ) << std::endl;
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  list
+    //  The output format description used below adds special item formatting
+    ///////////////////////////////////////////////////////////////////////////
+    std::list<std::string> names;
+    names.push_back("Spirit");
+    names.push_back("Qi");
+    names.push_back("Karma");
+
+    // specifying a prefix item suffix scheme directly
+    std::cout << 
+        karma::format(
+            ('{' << stream << '}') % ", ",        // format description
+            names                                 // data
+        ) << std::endl;
+
+    //  The confix generator nicely wraps the given expression with prefix and 
+    //  suffix strings
+    std::cout << 
+        karma::format(
+            confix(stream % ", ", "[", "]"),      // format description
+            names                                 // data
+        ) << std::endl;
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  Output the given container as a list
+    //  We use a separate metafunction list_impl_mf to specify the expected 
+    //  parameter type of this functor generator. 
+    //  We use phoenix::bind to allow to omit the 2nd argument from the functor
+    //  function operator and to change the sequence of the remaining two 
+    //  arguments.
+    ///////////////////////////////////////////////////////////////////////////
+    std::string str("Hello world!");
+    std::cout << 
+        karma::format(
+            karma::as_generator_mf<list_impl_mf>(bind(list(stream, ", "), _3, _1)),
+            str
+        ) << std::endl;
+    
+    return 0;
+}
Added: trunk/libs/spirit/example/karma/quick_start1.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/karma/quick_start1.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,119 @@
+//  Copyright (c) 2001-2008 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 container type can
+//  be formatted using different output grammars. 
+
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_stream.hpp>
+
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <cstdlib> 
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+namespace karma = boost::spirit::karma;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // vector
+    std::vector<int> v (8);
+    std::generate(v.begin(), v.end(), std::rand); // randomly fill the vector
+
+    std::cout << "Output 8 integers from a std::vector<int>..." << std::endl;
+
+    // output the container as a sequence without any separation
+    std::cout << "...without any separation" << std::endl;
+    std::cout << 
+        karma::format(
+            *int_,                                // format description
+            v                                     // data
+        ) << std::endl << std::endl;
+
+    // output the container as a space separated sequence
+    std::cout << "...as space delited list" << std::endl;
+    std::cout << 
+        karma::format_delimited(
+            *int_,                                // format description
+            v,                                    // data
+            space                                 // delimiter
+        ) << std::endl << std::endl;
+
+    std::cout << 
+        karma::format_delimited(
+            '[' << *int_ << ']',                  // format description
+            v,                                    // data
+            space                                 // delimiter
+        ) << std::endl << std::endl;
+
+    // output the container as a comma separated list
+    std::cout << "...as comma separated list" << std::endl;
+    std::cout << 
+        karma::format(
+            int_ % ", ",                          // format description
+            v                                     // data
+        ) << std::endl << std::endl;
+
+    std::cout << 
+        karma::format(
+            '[' << (int_ % ", ") << ']',          // format description
+            v                                     // data
+        ) << std::endl << std::endl;
+
+    // output the container as a comma separated list of double's
+    std::cout << "...as comma separated list of doubles" << std::endl;
+    std::cout << 
+        karma::format(
+            double_ % ", ",                       // format description
+            v                                     // data
+        ) << std::endl << std::endl;
+
+    // output the container as a comma separated list of items enclosed in '()'
+    std::cout << "..as list of ints enclosed in '()'" << std::endl;
+    std::cout << 
+        karma::format(
+            ('(' << int_ << ')') % ", ",          // format description
+            v                                     // data
+        ) << std::endl << std::endl;
+
+    std::cout << 
+        karma::format(
+            '[' << (  
+                ('(' << int_ << ')') % ", "
+             )  << ']',                           // format description
+            v                                     // data
+        ) << std::endl << std::endl;
+        
+    // output the container as a HTML list
+    std::cout << "...as HTML bullet list" << std::endl;
+    std::cout << 
+        karma::format_delimited(
+            "<ol>" << 
+                // no delimiting within verbatim
+                *verbatim["  <li>" << int_ << "</li>"]
+            << "</ol>",                           // format description
+            v,                                    // data
+            '\n'                                  // delimiter
+        ) << std::endl;
+
+    // output the container as right aligned column
+    std::cout << "...right aligned in a column" << std::endl;
+    std::cout << 
+        karma::format_delimited(
+           *verbatim[
+                "|" << right_align[int_] << "|"
+            ],                                    // format description
+            v,                                    // data
+            '\n'                                  // delimiter
+        ) << std::endl;
+
+    std::cout << std::endl;
+    return 0;
+}
+
Added: trunk/libs/spirit/example/lex/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/Jamfile	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,22 @@
+#==============================================================================
+#   Copyright (c) 2001-2007 Joel de Guzman
+#   Copyright (c) 2001-2008 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)
+#==============================================================================
+
+project spirit-lexer-example ;
+
+exe example1            : example1.cpp ;
+exe example2            : example2.cpp ;
+exe example3            : example3.cpp ;
+exe example4            : example4.cpp ;
+exe example5            : example5.cpp ;
+exe example6            : example6.cpp ;
+exe print_numbers       : print_numbers.cpp ;
+exe word_count          : word_count.cpp ;
+exe word_count_functor  : word_count_functor.cpp ;
+exe word_count_lexer    : word_count_lexer.cpp ;
+exe strip_comments      : strip_comments.cpp ;
+
Added: trunk/libs/spirit/example/lex/example.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/example.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,26 @@
+//  Copyright (c) 2001-2008 Hartmut Kaiser
+//  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)
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+///////////////////////////////////////////////////////////////////////////////
+//  Helper function reading a file into a string
+///////////////////////////////////////////////////////////////////////////////
+inline std::string 
+read_from_file(char const* infile)
+{
+    std::ifstream instream(infile);
+    if (!instream.is_open()) {
+        std::cerr << "Couldn't open file: " << infile << std::endl;
+        exit(-1);
+    }
+    instream.unsetf(std::ios::skipws);      // No white space skipping!
+    return std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
+                       std::istreambuf_iterator<char>());
+}
+
Added: trunk/libs/spirit/example/lex/example1.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/example1.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,136 @@
+//  Copyright (c) 2001-2008 Hartmut Kaiser
+//  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)
+
+//  Simple lexer/parser to test the Spirit installation.
+//
+//  This example shows, how to create a simple lexer recognizing 4 different 
+//  tokens, and how to use a single token definition as the skip parser during 
+//  the parsing. Additionally it demonstrates how to use one of the defined 
+//  tokens as a parser component in the grammar.
+//
+//  The grammar recognizes a simple input structure, for instance:
+//
+//        {
+//            hello world, hello it is me
+//        }
+//
+//  Any number of simple sentences (optionally comma separated) inside a pair 
+//  of curly braces will be matched.
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example1_tokens : lexer_def<Lexer>
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define tokens and associate them with the lexer
+        identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+        self = token_def<>(',') | '{' | '}' | identifier;
+        
+        // any token definition to be used as the skip parser during parsing 
+        // has to be associated with a separate lexer state (here 'WS') 
+        white_space = "[ \\t\\n]+";
+        self("WS") = white_space;
+    }
+    
+    token_def<> identifier, white_space;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct example1_grammar 
+  : grammar_def<Iterator, in_state_skipper<token_def<> > >
+{
+    template <typename TokenDef>
+    example1_grammar(TokenDef const& tok)
+    {
+        start = '{' >> *(tok.identifier >> -char_(',')) >> '}';
+    }
+
+    rule<Iterator, in_state_skipper<token_def<> > > start;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+    
+    // This is the token type to return from the lexer iterator
+    typedef lexertl_token<base_iterator_type> token_type;
+    
+    // This is the lexer type to use to tokenize the input.
+    // We use the lexertl based lexer engine.
+    typedef lexertl_lexer<token_type> lexer_type;
+    
+    // This is the token definition type (derived from the given lexer type).
+    typedef example1_tokens<lexer_type> example1_tokens;
+    
+    // This is the iterator type exposed by the lexer 
+    typedef lexer<example1_tokens>::iterator_type iterator_type;
+
+    // This is the type of the grammar to parse
+    typedef example1_grammar<iterator_type> example1_grammar;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    example1_tokens tokens;                         // Our token definition
+    example1_grammar def (tokens);                  // Our grammar definition
+
+    lexer<example1_tokens> lex(tokens);             // Our lexer
+    grammar<example1_grammar> calc(def);            // Our parser
+
+    std::string str (read_from_file("example1.input"));
+
+    // At this point we generate the iterator pair used to expose the
+    // tokenized input stream.
+    std::string::iterator it = str.begin();
+    iterator_type iter = lex.begin(it, str.end());
+    iterator_type end = lex.end();
+
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    // Note, how we use the token_def defined above as the skip parser. It must
+    // be explicitly wrapped inside a state directive, switching the lexer 
+    // state for the duration of skipping whitespace.
+    bool r = phrase_parse(iter, end, calc, in_state("WS")[tokens.white_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;
+}
Added: trunk/libs/spirit/example/lex/example2.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/example2.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,169 @@
+//  Copyright (c) 2001-2008 Hartmut Kaiser
+//  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)
+
+//  This example shows how to create a simple lexer recognizing a couple of 
+//  different tokens and how to use this with a grammar. This example has a 
+//  heavily backtracking grammar which makes it a candidate for lexer based 
+//  parsing (all tokens are scanned and generated only once, even if 
+//  backtracking is required) which speeds up the overall parsing process 
+//  considerably, out-weighting the overhead needed for setting up the lexer.
+//  Additionally it demonstrates how to use one of the defined tokens as a 
+//  parser component in the grammar.
+//
+//  The grammar recognizes a simple input structure: any number of English 
+//  simple sentences (statements, questions and commands) are recognized and
+//  are being counted separately.
+
+// #define BOOST_SPIRIT_DEBUG 
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+using boost::phoenix::ref;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example2_tokens : lexer_def<Lexer>
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        //  A 'word' is comprised of one or more letters and an optional 
+        //  apostrophe. If it contains an apostrophe, there may only be one and 
+        //  the apostrophe must be preceded and succeeded by at least 1 letter.  
+        //  For example, "I'm" and "doesn't" meet the definition of 'word' we 
+        //  define below.
+        word = "[a-zA-Z]+('[a-zA-Z]+)?";
+        
+        // associate the tokens and the token set with the lexer
+        self = token_def<>(',') | '!' | '.' | '?' | ' ' | '\n' | word;
+    }
+    
+    token_def<> word;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct example2_grammar : grammar_def<Iterator>
+{
+    template <typename TokenDef>
+    example2_grammar(TokenDef const& tok)
+      : paragraphs(0), commands(0), questions(0), statements(0)
+    {
+        story 
+            =  +paragraph
+            ;
+
+        paragraph
+            =   (  +(   command [ ++ref(commands) ] 
+                    |   question [ ++ref(questions) ]
+                    |   statement [ ++ref(statements) ]
+                    ) 
+                    >> *char_(' ') >> +char_('\n')
+                ) 
+                [ ++ref(paragraphs) ]
+            ;
+
+        command 
+            =  +(tok.word | ' ' | ',') >> '!' 
+            ;
+
+        question 
+            =  +(tok.word | ' ' | ',') >> '?' 
+            ;
+
+        statement 
+            =  +(tok.word | ' ' | ',') >> '.' 
+            ;
+
+        BOOST_SPIRIT_DEBUG_NODE(story);
+        BOOST_SPIRIT_DEBUG_NODE(paragraph);
+        BOOST_SPIRIT_DEBUG_NODE(command);
+        BOOST_SPIRIT_DEBUG_NODE(question);
+        BOOST_SPIRIT_DEBUG_NODE(statement);
+    }
+
+    rule<Iterator> story, paragraph, command, question, statement;
+    int paragraphs, commands, questions, statements;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+    
+    // This is the token type to return from the lexer iterator
+    typedef lexertl_token<base_iterator_type> token_type;
+    
+    // This is the lexer type to use to tokenize the input.
+    // Here we use the lexertl based lexer engine.
+    typedef lexertl_lexer<token_type> lexer_type;
+    
+    // This is the token definition type (derived from the given lexer type).
+    typedef example2_tokens<lexer_type> example2_tokens;
+    
+    // this is the iterator type exposed by the lexer 
+    typedef lexer<example2_tokens>::iterator_type iterator_type;
+
+    // this is the type of the grammar to parse
+    typedef example2_grammar<iterator_type> example2_grammar;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    example2_tokens tokens;                         // Our token definition
+    example2_grammar def (tokens);                  // Our grammar definition
+
+    lexer<example2_tokens> lex(tokens);             // Our lexer
+    grammar<example2_grammar> calc(def, def.story); // Our grammar
+
+    std::string str (read_from_file("example2.input"));
+
+    // At this point we generate the iterator pair used to expose the
+    // tokenized input stream.
+    std::string::iterator it = str.begin();
+    iterator_type iter = lex.begin(it, str.end());
+    iterator_type end = lex.end();
+        
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    bool r = parse(iter, end, calc);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "There were " 
+                  << def.commands << " commands, " 
+                  << def.questions << " questions, and " 
+                  << def.statements << " statements.\n";
+        std::cout << "-------------------------\n";
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
Added: trunk/libs/spirit/example/lex/example3.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/example3.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,161 @@
+//  Copyright (c) 2001-2008 Hartmut Kaiser
+//  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)
+
+//  This example shows how to create a simple lexer recognizing a couple of 
+//  different tokens and how to use this with a grammar. This example has a 
+//  heavily backtracking grammar which makes it a candidate for lexer based 
+//  parsing (all tokens are scanned and generated only once, even if 
+//  backtracking is required) which speeds up the overall parsing process 
+//  considerably, out-weighting the overhead needed for setting up the lexer.
+//
+//  Additionally, this example demonstrates, how to define a token set usable 
+//  as the skip parser during parsing, allowing to define several tokens to be 
+//  ignored.
+//
+//  This example recognizes couplets, which are sequences of numbers enclosed 
+//  in matching pairs of parenthesis. See the comments below to for details
+//  and examples.
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+// #define BOOST_SPIRIT_DEBUG
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example3_tokens : lexer_def<Lexer>
+{
+    typedef typename Lexer::token_set token_set;
+    
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define the tokens to match
+        ellipses = "\\.\\.\\.";
+        number = "[0-9]+";
+        
+        // define the whitespace to ignore (spaces, tabs, newlines and C-style 
+        // comments)
+        white_space 
+            =   token_def<>("[ \\t\\n]+")               // whitespace
+            |   "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"   // C style comments
+            ;
+        
+        // associate the tokens and the token set with the lexer
+        self = ellipses | '(' | ')' | number;
+        self("WS") = white_space;
+    }
+    
+    // these tokens expose the iterator_range of the matched input sequence
+    token_def<> ellipses, identifier, number;
+    token_set white_space;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example3_grammar 
+  : grammar_def<Iterator, in_state_skipper<typename Lexer::token_set> >
+{
+    template <typename TokenDef>
+    example3_grammar(TokenDef const& tok)
+    {
+        start 
+            =  +(couplet | tok.ellipses)
+            ;
+
+        //  A couplet matches nested left and right parenthesis.
+        //  For example:
+        //    (1) (1 2) (1 2 3) ...
+        //    ((1)) ((1 2)(3 4)) (((1) (2 3) (1 2 (3) 4))) ...
+        //    (((1))) ...
+        couplet
+            =   tok.number
+            |   '(' >> +couplet >> ')'
+            ;
+
+        BOOST_SPIRIT_DEBUG_NODE(start);
+        BOOST_SPIRIT_DEBUG_NODE(couplet);
+    }
+
+    typedef typename Lexer::token_set token_set;
+    rule<Iterator, in_state_skipper<token_set> > start, couplet;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+    
+    // This is the token type to return from the lexer iterator
+    typedef lexertl_token<base_iterator_type> token_type;
+    
+    // This is the lexer type to use to tokenize the input.
+    // Here we use the lexertl based lexer engine.
+    typedef lexertl_lexer<token_type> lexer_type;
+    
+    // This is the token definition type (derived from the given lexer type).
+    typedef example3_tokens<lexer_type> example3_tokens;
+    
+    // this is the iterator type exposed by the lexer 
+    typedef lexer<example3_tokens>::iterator_type iterator_type;
+
+    // this is the type of the grammar to parse
+    typedef example3_grammar<iterator_type, lexer_type> example3_grammar;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    example3_tokens tokens;                         // Our token definition
+    example3_grammar def (tokens);                  // Our grammar definition
+
+    lexer<example3_tokens> lex(tokens);             // Our lexer
+    grammar<example3_grammar> calc(def);            // Our grammar
+
+    std::string str (read_from_file("example3.input"));
+
+    // At this point we generate the iterator pair used to expose the
+    // tokenized input stream.
+    std::string::iterator it = str.begin();
+    iterator_type iter = lex.begin(it, str.end());
+    iterator_type end = lex.end();
+        
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    // Note, how we use the token_set defined above as the skip parser.
+    std::string ws("WS");
+    bool r = phrase_parse(iter, end, calc, in_state(ws)[tokens.white_space]);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
Added: trunk/libs/spirit/example/lex/example4.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/example4.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,239 @@
+//  Copyright (c) 2001-2008 Hartmut Kaiser
+//  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)
+
+//  This example shows how to create a simple lexer recognizing a couple of 
+//  different tokens aimed at a simple language and how to use this lexer with 
+//  a grammar. It shows how to associate values to tokens and how to access the 
+//  token values from inside the grammar.
+//
+//  We use explicit token value types, making the corresponding token instances
+//  carry convert the matched input into an instance of that type. The token 
+//  value is exposed as the parser attribute if this token is used as a 
+//  parser component somewhere in a grammar.
+//
+//  Additionally, this example demonstrates, how to define a token set usable 
+//  as the skip parser during parsing, allowing to define several tokens to be 
+//  ignored.
+//
+//  This example recognizes a very simple programming language having 
+//  assignment statements and if and while control structures. Look at the file
+//  example4.input for an example.
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::val;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example4_tokens : lexer_def<Lexer>
+{
+    typedef typename Lexer::token_set token_set;
+    
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define the tokens to match
+        identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+        constant = "[0-9]+";
+        if_ = "if";
+        else_ = "else";
+        while_ = "while";
+        
+        // define the whitespace to ignore (spaces, tabs, newlines and C-style 
+        // comments)
+        white_space 
+            =   token_def<>("[ \\t\\n]+") 
+            |   "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
+            ;
+        
+        // associate the tokens and the token set with the lexer
+        self = token_def<>('(') | ')' | '{' | '}' | '=' | ';' | constant;
+        self += if_ | else_ | while_ | identifier;
+        self("WS") = white_space;
+    }
+
+//[example4_token_def
+    // these tokens expose the iterator_range of the matched input sequence
+    token_def<> if_, else_, while_;
+    
+    // The following two tokens have an associated value type, 'identifier'
+    // carries a string (the identifier name) and 'constant' carries the 
+    // matched integer value.
+    //
+    // Note: any token value type specified explicitly during a token_def<>
+    //       declaration needs to be listed during token type definition as 
+    //       well (see the typedef for the token_type below).
+    //
+    // The conversion of the matched input to an instance of this type occurs
+    // once (on first access), which makes token values as efficient as 
+    // possible. Moreover, token instances are constructed once by the lexer
+    // library. From this point on tokens are passed by reference only, 
+    // avoiding tokens being copied around.
+    token_def<std::string> identifier;
+    token_def<unsigned int> constant;
+//]
+
+    // token set to be used as the skip parser
+    token_set white_space;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example4_grammar 
+  : grammar_def<Iterator, in_state_skipper<typename Lexer::token_set> >
+{
+    template <typename TokenDef>
+    example4_grammar(TokenDef const& tok)
+    {
+        program 
+            =  +block
+            ;
+
+        block
+            =   '{' >> *statement >> '}'
+            ;
+
+        statement 
+            =   assignment
+            |   if_stmt
+            |   while_stmt
+            ;
+
+        assignment 
+            =   (tok.identifier >> '=' >> expression >> ';')
+                [
+                    std::cout << val("assignment statement to: ") << _1 << "\n"
+                ]
+            ;
+
+        if_stmt
+            =   (   tok.if_ >> '(' >> expression >> ')' >> block 
+                    >> -(tok.else_ >> block) 
+                )
+                [
+                    std::cout << val("if expression: ") << _2 << "\n"
+                ]
+            ;
+
+        while_stmt 
+            =   (tok.while_ >> '(' >> expression >> ')' >> block)
+                [
+                    std::cout << val("while expression: ") << _2 << "\n"
+                ]
+            ;
+
+        //  since expression has a variant return type accommodating for 
+        //  std::string and unsigned integer, both possible values may be 
+        //  returned to the calling rule
+        expression 
+            =   tok.identifier [ _val = _1 ]
+            |   tok.constant   [ _val = _1 ]
+            ;
+    }
+
+    typedef typename Lexer::token_set token_set;
+    typedef boost::variant<unsigned int, std::string> expression_type;
+    
+    rule<Iterator, in_state_skipper<token_set> > program, block, statement;
+    rule<Iterator, in_state_skipper<token_set> > assignment, if_stmt;
+    rule<Iterator, in_state_skipper<token_set> > while_stmt;
+    
+    //  the expression is the only rule having a return value
+    rule<Iterator, expression_type(), in_state_skipper<token_set> >  expression;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+    
+//[example4_token
+    // This is the lexer token type to use. The second template parameter lists 
+    // all attribute types used for token_def's during token definition (see 
+    // calculator_tokens<> above). Here we use the predefined lexertl token 
+    // type, but any compatible token type may be used instead.
+    //
+    // If you don't list any token value types in the following declaration 
+    // (or just use the default token type: lexertl_token<base_iterator_type>)  
+    // it will compile and work just fine, just a bit less efficient. This is  
+    // because the token value will be generated from the matched input  
+    // sequence every time it is requested. But as soon as you specify at 
+    // least one token value type you'll have to list all value types used  
+    // for token_def<> declarations in the token definition class above,  
+    // otherwise compilation errors will occur.
+    typedef lexertl_token<
+        base_iterator_type, boost::mpl::vector<unsigned int, std::string> 
+    > token_type;
+//]
+    // Here we use the lexertl based lexer engine.
+    typedef lexertl_lexer<token_type> lexer_type;
+    
+    // This is the token definition type (derived from the given lexer type).
+    typedef example4_tokens<lexer_type> example4_tokens;
+    
+    // this is the iterator type exposed by the lexer 
+    typedef lexer<example4_tokens>::iterator_type iterator_type;
+
+    // this is the type of the grammar to parse
+    typedef example4_grammar<iterator_type, lexer_type> example4_grammar;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    example4_tokens tokens;                         // Our token definition
+    example4_grammar def (tokens);                  // Our grammar definition
+
+    lexer<example4_tokens> lex(tokens);                 // Our lexer
+    grammar<example4_grammar> calc(def, def.program);   // Our grammar
+
+    std::string str (read_from_file("example4.input"));
+
+    // At this point we generate the iterator pair used to expose the
+    // tokenized input stream.
+    std::string::iterator it = str.begin();
+    iterator_type iter = lex.begin(it, str.end());
+    iterator_type end = lex.end();
+        
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    // Note, how we use the token_set defined above as the skip parser. It must
+    // be explicitly wrapped inside a state directive, switching the lexer 
+    // state for the duration of skipping whitespace.
+    bool r = phrase_parse(iter, end, calc, in_state("WS")[tokens.white_space]);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
Added: trunk/libs/spirit/example/lex/example5.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/example5.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,283 @@
+//  Copyright (c) 2001-2008 Hartmut Kaiser
+//  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)
+
+//  This example shows how to create a simple lexer recognizing a couple of 
+//  different tokens aimed at a simple language and how to use this lexer with 
+//  a grammar. It shows how to associate values to tokens and how to access the 
+//  token values from inside the grammar.
+//
+//  Additionally, this example demonstrates, how to define a token set usable 
+//  as the skip parser during parsing, allowing to define several tokens to be 
+//  ignored.
+//
+//  The main purpose of this example is to show, how inheritance can be used to 
+//  overload parts of a base grammar and add token definitions to a base lexer.
+//
+//  Further, it shows how you can use the 'omitted' attribute type specifier 
+//  for token definitions to force the token to have no attribute (expose an 
+//  unused attribute).
+//
+//  This example recognizes a very simple programming language having 
+//  assignment statements and if and while control structures. Look at the file
+//  example5.input for an example.
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::val;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition base, defines all tokens for the base grammar below
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example5_base_tokens : lexer_def<Lexer>
+{
+    typedef typename Lexer::token_set token_set;
+    
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define the tokens to match
+        identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+        constant = "[0-9]+";
+        if_ = "if";
+        while_ = "while";
+        
+        // define the whitespace to ignore (spaces, tabs, newlines and C-style 
+        // comments)
+        white_space 
+            =   token_def<>("[ \\t\\n]+") 
+            |   "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
+            ;
+        
+        // associate the tokens and the token set with the lexer
+        self += token_def<>('(') | ')' | '{' | '}' | '=' | ';' | constant;
+        self += if_ | while_ | identifier;
+        self("WS") = white_space;
+    }
+    
+    // these tokens have no value
+    token_def<omitted> if_, while_;
+    
+    // The following two tokens have an associated value type, identifier 
+    // carries a string (the identifier name) and constant carries the matched 
+    // integer value.
+    //
+    // Note: any explicitly token value type specified during a token_def<>
+    //       declaration needs to be listed during token type definition as 
+    //       well (see the typedef for the token_type below).
+    //
+    // The conversion of the matched input to an instance of this type occurs
+    // once (on first access), which makes token values as efficient as 
+    // possible. Moreover, token instances are constructed once by the lexer
+    // library. From this point on tokens are passed by reference only, 
+    // avoiding tokens being copied around.
+    token_def<std::string> identifier;
+    token_def<unsigned int> constant;
+
+    // token set to be used as the skip parser
+    token_set white_space;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition base, defines a basic language
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example5_base_grammar 
+  : grammar_def<Iterator, in_state_skipper<typename Lexer::token_set> >
+{
+    template <typename TokenDef>
+    example5_base_grammar(TokenDef const& tok)
+    {
+        program 
+            =  +block
+            ;
+
+        block
+            =   '{' >> *statement >> '}'
+            ;
+
+        statement 
+            =   assignment
+            |   if_stmt
+            |   while_stmt
+            ;
+
+        assignment 
+            =   (tok.identifier >> '=' >> expression >> ';')
+                [
+                    std::cout << val("assignment statement to: ") << _1 << "\n"
+                ]
+            ;
+
+        if_stmt
+            =   (tok.if_ >> '(' >> expression >> ')' >> block)
+                [
+                    std::cout << val("if expression: ") << _1 << "\n"
+                ]
+            ;
+
+        while_stmt 
+            =   (tok.while_ >> '(' >> expression >> ')' >> block)
+                [
+                    std::cout << val("while expression: ") << _1 << "\n"
+                ]
+            ;
+
+        //  since expression has a variant return type accommodating for 
+        //  std::string and unsigned integer, both possible values may be 
+        //  returned to the calling rule
+        expression 
+            =   tok.identifier [ _val = _1 ]
+            |   tok.constant   [ _val = _1 ]
+            ;
+    }
+
+    typedef 
+        grammar_def<Iterator, in_state_skipper<typename Lexer::token_set> > 
+    base_type;
+    typedef typename base_type::skipper_type skipper_type;
+    
+    rule<Iterator, skipper_type> program, block, statement;
+    rule<Iterator, skipper_type> assignment, if_stmt;
+    rule<Iterator, skipper_type> while_stmt;
+    
+    //  the expression is the only rule having a return value
+    typedef boost::variant<unsigned int, std::string> expression_type;
+    rule<Iterator, expression_type(), skipper_type>  expression;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition for derived lexer, defines additional tokens 
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example5_tokens : example5_base_tokens<Lexer>
+{
+    typedef typename Lexer::token_set token_set;
+    
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define the additional token to match
+        else_ = "else";
+        
+        // associate the new token with the lexer, note we add 'else' before 
+        // anything else to add it to the token set before the identifier 
+        // token, otherwise "else" would be matched as an identifier
+        self = else_;
+        
+        // call the base class definition function
+        example5_base_tokens<Lexer>::def(self);
+    }
+    
+    // this token has no value
+    token_def<omitted> else_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Derived grammar definition, defines a language extension
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example5_grammar : example5_base_grammar<Iterator, Lexer>
+{
+    template <typename TokenDef>
+    example5_grammar(TokenDef const& tok)
+      : example5_base_grammar<Iterator, Lexer>(tok)
+    {
+        // we alter the if_stmt only
+        this->if_stmt
+            =   this->if_stmt.copy() >> -(tok.else_ >> this->block)
+            ;
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+    
+    // This is the lexer token type to use. The second template parameter lists 
+    // all attribute types used for token_def's during token definition (see 
+    // calculator_tokens<> above). Here we use the predefined lexertl token 
+    // type, but any compatible token type may be used instead.
+    //
+    // If you don't list any token value types in the following declaration 
+    // (or just use the default token type: lexertl_token<base_iterator_type>)  
+    // it will compile and work just fine, just a bit less efficient. This is  
+    // because the token value will be generated from the matched input  
+    // sequence every time it is requested. But as soon as you specify at 
+    // least one token value type you'll have to list all value types used  
+    // for token_def<> declarations in the token definition class above,  
+    // otherwise compilation errors will occur.
+    typedef lexertl_token<
+        base_iterator_type, boost::mpl::vector<unsigned int, std::string> 
+    > token_type;
+    
+    // Here we use the lexertl based lexer engine.
+    typedef lexertl_lexer<token_type> lexer_type;
+    
+    // This is the token definition type (derived from the given lexer type).
+    typedef example5_tokens<lexer_type> example5_tokens;
+    
+    // this is the iterator type exposed by the lexer 
+    typedef lexer<example5_tokens>::iterator_type iterator_type;
+
+    // this is the type of the grammar to parse
+    typedef example5_grammar<iterator_type, lexer_type> example5_grammar;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    example5_tokens tokens;                         // Our token definition
+    example5_grammar def (tokens);                  // Our grammar definition
+
+    lexer<example5_tokens> lex(tokens);                 // Our lexer
+    grammar<example5_grammar> calc(def, def.program);   // Our grammar
+
+    std::string str (read_from_file("example5.input"));
+
+    // At this point we generate the iterator pair used to expose the
+    // tokenized input stream.
+    std::string::iterator it = str.begin();
+    iterator_type iter = lex.begin(it, str.end());
+    iterator_type end = lex.end();
+        
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    // Note, how we use the token_set defined above as the skip parser. It must
+    // be explicitly wrapped inside a state directive, switching the lexer 
+    // state for the duration of skipping whitespace.
+    std::string ws("WS");
+    bool r = phrase_parse(iter, end, calc, in_state(ws)[tokens.white_space]);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
Added: trunk/libs/spirit/example/lex/example6.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/example6.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,263 @@
+//  Copyright (c) 2001-2008 Hartmut Kaiser
+//  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)
+
+//  This example shows how to create a simple lexer recognizing a couple of 
+//  different tokens aimed at a simple language and how to use this lexer with 
+//  a grammar. It shows how to associate values to tokens and how to access the 
+//  token values from inside the grammar.
+//
+//  Additionally, this example demonstrates, how to define a token set usable 
+//  as the skip parser during parsing, allowing to define several tokens to be 
+//  ignored.
+//
+//  The example demonstrates how to use the add(...)(...) syntax to associate 
+//  token definitions with the lexer and how token ids can be used in the 
+//  parser to refer to a token, without having to directly reference its 
+//  definition.
+//
+//  This example recognizes a very simple programming language having 
+//  assignment statements and if and while control structures. Look at the file
+//  example6.input for an example.
+//
+//  This example is essentially identical to example4.cpp. The only difference 
+//  is that we use the self.add() syntax to define tokens and to associate them
+//  with the lexer.
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::val;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token id definitions
+///////////////////////////////////////////////////////////////////////////////
+enum token_ids
+{
+    ID_CONSTANT = 1000,
+    ID_IF,
+    ID_ELSE,
+    ID_WHILE,
+    ID_IDENTIFIER
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definitions
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example6_tokens : lexer_def<Lexer>
+{
+    typedef typename Lexer::token_set token_set;
+    
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define the tokens to match
+        identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+        constant = "[0-9]+";
+        
+        // define the whitespace to ignore (spaces, tabs, newlines and C-style 
+        // comments)
+        white_space 
+            =   token_def<>("[ \\t\\n]+") 
+            |   "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
+            ;
+        
+        // associate the tokens and the token set with the lexer
+        self = token_def<>('(') | ')' | '{' | '}' | '=' | ';';
+        
+        // Token definitions can be added by using some special syntactic 
+        // construct as shown below.
+        // Note, that the token definitions added this way expose the iterator
+        // pair pointing to the matched input stream as their attribute.
+        self.add
+            (constant, ID_CONSTANT)
+            ("if", ID_IF)
+            ("else", ID_ELSE)
+            ("while", ID_WHILE)
+            (identifier, ID_IDENTIFIER)
+        ;
+        
+        // add whitespace tokens to another lexer state (here: "WS")
+        self("WS") = white_space;
+    }
+    
+    // The following two tokens have an associated value type, identifier 
+    // carries a string (the identifier name) and constant carries the matched 
+    // integer value.
+    //
+    // Note: any explicitly token value type specified during a token_def<>
+    //       declaration needs to be listed during token type definition as 
+    //       well (see the typedef for the token_type below).
+    //
+    // The conversion of the matched input to an instance of this type occurs
+    // once (on first access), which makes token values as efficient as 
+    // possible. Moreover, token instances are constructed once by the lexer
+    // library. From this point on tokens are passed by reference only, 
+    // avoiding tokens being copied around.
+    token_def<std::string> identifier;
+    token_def<unsigned int> constant;
+
+    // token set to be used as the skip parser
+    token_set white_space;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example6_grammar 
+  : grammar_def<Iterator, in_state_skipper<typename Lexer::token_set> >
+{
+    template <typename TokenDef>
+    example6_grammar(TokenDef const& tok)
+    {
+        program 
+            =  +block
+            ;
+
+        block
+            =   '{' >> *statement >> '}'
+            ;
+
+        statement 
+            =   assignment
+            |   if_stmt
+            |   while_stmt
+            ;
+
+        assignment 
+            =   (tok.identifier >> '=' >> expression >> ';')
+                [
+                    std::cout << val("assignment statement to: ")
+                              << _1 << "\n"
+                ]
+            ;
+
+        if_stmt
+            =   (   token(ID_IF) >> '(' >> expression >> ')' >> block 
+                >> -(token(ID_ELSE) >> block) 
+                )
+                [
+                    std::cout << val("if expression: ")
+                              << _2 << "\n"
+                ]
+            ;
+
+        while_stmt 
+            =   (token(ID_WHILE) >> '(' >> expression >> ')' >> block)
+                [
+                    std::cout << val("while expression: ")
+                              << _2 << "\n"
+                ]
+            ;
+
+        //  since expression has a variant return type accommodating for 
+        //  std::string and unsigned integer, both possible values may be 
+        //  returned to the calling rule
+        expression 
+            =   tok.identifier [ _val = _1 ]
+            |   tok.constant   [ _val = _1 ]
+            ;
+    }
+
+    typedef typename Lexer::token_set token_set;
+    typedef boost::variant<unsigned int, std::string> expression_type;
+    
+    rule<Iterator, in_state_skipper<token_set> > program, block, statement;
+    rule<Iterator, in_state_skipper<token_set> > assignment, if_stmt;
+    rule<Iterator, in_state_skipper<token_set> > while_stmt;
+    
+    //  the expression is the only rule having a return value
+    rule<Iterator, expression_type(), in_state_skipper<token_set> >  expression;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+    
+    // This is the lexer token type to use. The second template parameter lists 
+    // all attribute types used for token_def's during token definition (see 
+    // calculator_tokens<> above). Here we use the predefined lexertl token 
+    // type, but any compatible token type may be used instead.
+    //
+    // If you don't list any token value types in the following declaration 
+    // (or just use the default token type: lexertl_token<base_iterator_type>)  
+    // it will compile and work just fine, just a bit less efficient. This is  
+    // because the token value will be generated from the matched input  
+    // sequence every time it is requested. But as soon as you specify at 
+    // least one token value type you'll have to list all value types used  
+    // for token_def<> declarations in the token definition class above,  
+    // otherwise compilation errors will occur.
+    typedef lexertl_token<
+        base_iterator_type, boost::mpl::vector<unsigned int, std::string> 
+    > token_type;
+    
+    // Here we use the lexertl based lexer engine.
+    typedef lexertl_lexer<token_type> lexer_type;
+    
+    // This is the token definition type (derived from the given lexer type).
+    typedef example6_tokens<lexer_type> example6_tokens;
+    
+    // this is the iterator type exposed by the lexer 
+    typedef lexer<example6_tokens>::iterator_type iterator_type;
+
+    // this is the type of the grammar to parse
+    typedef example6_grammar<iterator_type, lexer_type> example6_grammar;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    example6_tokens tokens;                         // Our token definition
+    example6_grammar def (tokens);                  // Our grammar definition
+
+    lexer<example6_tokens> lex(tokens);                 // Our lexer
+    grammar<example6_grammar> calc(def, def.program);   // Our grammar
+
+    std::string str (read_from_file("example6.input"));
+
+    // At this point we generate the iterator pair used to expose the
+    // tokenized input stream.
+    std::string::iterator it = str.begin();
+    iterator_type iter = lex.begin(it, str.end());
+    iterator_type end = lex.end();
+        
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    // Note, how we use the token_def defined above as the skip parser. It must
+    // be explicitly wrapped inside a state directive, switching the lexer 
+    // state for the duration of skipping whitespace.
+    std::string ws("WS");
+    bool r = phrase_parse(iter, end, calc, in_state(ws)[tokens.white_space]);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
Added: trunk/libs/spirit/example/lex/print_numbers.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/print_numbers.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,118 @@
+//  Copyright (c) 2001-2008 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 is the equivalent to the following lex program:
+//
+//     %{
+//     #include <stdio.h>
+//     %}
+//     %%
+//     [0-9]+   { printf("%s\n", yytext); }
+//     .|\n     ;
+//     %%
+//     main()
+//     {
+//             yylex();
+//     }
+//
+//  Its purpose is to print all the (integer) numbers found in a file
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition: We use the lexertl based lexer engine as the underlying 
+//                    lexer type.
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct print_numbers_tokens : lexer_def<Lexer>
+{
+    // define tokens and associate it with the lexer
+    template <typename Self>
+    void def (Self& self)
+    {
+        self = token_def<int>("[0-9]*") | ".|\n";
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct print_numbers_grammar : grammar_def<Iterator>
+{
+    print_numbers_grammar()
+    {
+        start =  *(   token(lex::min_token_id)  [ std::cout << _1  << "\n" ] 
+                  |   token(lex::min_token_id+1)
+                  )
+              ;
+    }
+
+    rule<Iterator> start;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+
+    // the token type to be used, 'int' is available as the type of the token 
+    // value and no lexer state is supported
+    typedef lexertl_token<
+        base_iterator_type, boost::mpl::vector<int>, boost::mpl::false_
+    > token_type;
+    
+    // lexer type
+    typedef lexertl_lexer<token_type> lexer_type;
+    
+    // iterator type exposed by the lexer 
+    typedef 
+        lexer_iterator<print_numbers_tokens<lexer_type> >::type 
+    iterator_type;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    print_numbers_tokens<lexer_type> print_tokens;    // Our token definition
+    print_numbers_grammar<iterator_type> def;         // Our grammar definition
+
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    std::string str (read_from_file(1 == argc ? "print_numbers.input" : argv[1]));
+    base_iterator_type first = str.begin();
+    bool r = tokenize_and_parse(first, str.end(), make_lexer(print_tokens), 
+        make_parser(def));
+
+    if (r) {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+    }
+    else {
+        std::string rest(first, str.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;
+}
+
+
+
Added: trunk/libs/spirit/example/lex/static_lexer/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/static_lexer/Jamfile	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,13 @@
+#==============================================================================
+#   Copyright (c) 2001-2007 Joel de Guzman
+#   Copyright (c) 2001-2008 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)
+#==============================================================================
+
+project spirit-static-lexer-example ;
+
+exe generate_tables     : generate_tables.cpp ;
+exe word_count_static   : word_count_static.cpp ;
+
Added: trunk/libs/spirit/example/lex/static_lexer/word_count_generate.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/static_lexer/word_count_generate.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,42 @@
+//  Copyright (c) 2001-2008 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 it is possible to use a lexer 
+//  token definition for two purposes:
+//
+//    . To generate C++ code implementing a static lexical analyzer allowing
+//      to recognize all defined tokens (this file)
+//    . To integrate the generated C++ lexer into the /Spirit/ framework.
+//      (see the file: word_count_static.cpp)
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/lex/lexer/lexertl/lexertl_generate_static.hpp>
+
+#include <fstream>
+
+#include "word_count_tokens.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::lex;
+
+///////////////////////////////////////////////////////////////////////////////
+//[wc_static_generate_main
+int main(int argc, char* argv[])
+{
+    // create the lexer object instance needed to invoke the generator
+    word_count_tokens<lexertl_lexer<> > word_count; // the token definition
+
+    // open the output file, where the generated tokenizer function will be 
+    // written to
+    std::ofstream out(argc < 2 ? "word_count_static.hpp" : argv[1]);
+
+    // invoke the generator, passing the token definition, the output stream 
+    // and the name prefix of the tokenizing function to be generated
+    char const* function_name = (argc < 3 ? "" : argv[2]);
+    return generate_static(make_lexer(word_count), out, function_name) ? 0 : -1;
+}
+//]
Added: trunk/libs/spirit/example/lex/static_lexer/word_count_static.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/static_lexer/word_count_static.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,118 @@
+//  Copyright (c) 2001-2008 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 it is possible to use a lexer 
+//  token definition for two purposes:
+//
+//    . To generate C++ code implementing a static lexical analyzer allowing
+//      to recognize all defined tokens 
+//    . To integrate the generated C++ lexer into the /Spirit/ framework.
+//
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+#define BOOST_VARIANT_MINIMIZE_SIZE
+
+#include <boost/spirit/include/qi.hpp>
+//[wc_static_include
+#include <boost/spirit/include/lex_lexer_static_lexertl.hpp>
+//]
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_container.hpp>
+
+#include <iostream>
+#include <string>
+
+#include "../example.hpp"
+#include "word_count_tokens.hpp"    // token definition
+
+#include "word_count_static.hpp"    // generated tokenizer
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+//[wc_static_grammar
+//  This is an ordinary grammar definition following the rules defined by 
+//  Spirit.Qi. There is nothing specific about it, except it gets the token
+//  definition class instance passed to the constructor to allow accessing the
+//  embedded token_def<> instances.
+template <typename Iterator>
+struct word_count_grammar : grammar_def<Iterator>
+{
+    template <typename TokenDef>
+    word_count_grammar(TokenDef const& tok)
+      : c(0), w(0), l(0)
+    {
+        using boost::spirit::arg_names::_1;
+        using boost::phoenix::ref;
+        using boost::phoenix::size;
+        
+        //  associate the defined tokens with the lexer, at the same time 
+        //  defining the actions to be executed 
+        start =  *(   tok.word      [++ref(w), ref(c) += size(_1)]
+                  |   char_('\n')   [++ref(l), ++ref(c)] 
+                  |   token(IDANY)  [++ref(c)]
+                  )
+              ;
+    }
+
+    std::size_t c, w, l;      // counter for characters, words, and lines
+    rule<Iterator> start;
+};
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[wc_static_main
+int main(int argc, char* argv[])
+{
+    // Define the token type to be used: 'std::string' is available as the type 
+    // of the token value.
+    typedef lexertl_token<
+        char const*, boost::mpl::vector<std::string>
+    > token_type;
+
+    // Define the lexer type to be used as the base class for our token 
+    // definition.
+    //
+    // This is the only place where the code is different from an equivalent
+    // dynamic lexical analyzer. We use the `lexertl_static_lexer<>` instead of
+    // the `lexertl_lexer<>` as the base class for our token defintion type.
+    //
+    typedef lexertl_static_lexer<token_type> lexer_type;
+    
+    // Define the iterator type exposed by the lexer.
+    typedef lexer_iterator<word_count_tokens<lexer_type> >::type iterator_type;
+
+    // Now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process.
+    word_count_tokens<lexer_type> word_count;            // Our token definition
+    word_count_grammar<iterator_type> def (word_count);  // Our grammar definition
+
+    // Read in the file into memory.
+    std::string str (read_from_file(1 == argc ? "word_count.input" : argv[1]));
+    char const* first = str.c_str();
+    char const* last = &first[str.size()];
+    
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    bool r = tokenize_and_parse(first, last, make_lexer(word_count), 
+        make_parser(def));
+
+    if (r) {    // success
+        std::cout << "lines: " << def.l << ", words: " << def.w 
+                  << ", characters: " << def.c << "\n";
+    }
+    else {
+        std::string rest(first, last);
+        std::cerr << "Parsing failed\n" << "stopped at: \"" 
+                  << rest << "\"\n";
+    }
+    return 0;
+}
+//]
Added: trunk/libs/spirit/example/lex/static_lexer/word_count_static.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/static_lexer/word_count_static.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,111 @@
+// Copyright (c) 2008 Ben Hanson
+//
+// 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
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_Feb_13_2008_12_01_20)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_Feb_13_2008_12_01_20
+
+#include <boost/detail/iterator.hpp>
+#include <boost/spirit/support/detail/lexer/char_traits.hpp>
+
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::static namespace
+namespace boost { namespace spirit { namespace lex { namespace static_ {
+
+// this table defines the names of the lexer states
+char const* const lexer_state_names[1] = 
+{
+    "INITIAL",
+};
+
+template<typename Iterator>
+std::size_t next_token (std::size_t &start_state_, Iterator const& start_, 
+    Iterator &start_token_, Iterator const& end_)
+{
+    enum {end_state_index, id_index, state_index, bol_index, eol_index,
+        dead_state_index, dfa_offset};
+    static const std::size_t npos = static_cast<std::size_t>(~0);
+    static const std::size_t lookup_[256] = {8, 8, 8, 8, 8, 8, 8, 8,
+        8, 7, 6, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        7, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8,
+        8, 8, 8, 8, 8, 8, 8, 8};
+    static const std::size_t dfa_alphabet_ = 9;
+    static const std::size_t dfa_[45] = {0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 3,
+        4, 2, 1, 65536, 0, 0, 0, 0,
+        0, 0, 2, 1, 65537, 0, 0, 0,
+        0, 0, 0, 0, 1, 65538, 0, 0,
+        0, 0, 0, 0, 0};
+
+    if (start_token_ == end_) return 0;
+
+    const std::size_t *ptr_ = dfa_ + dfa_alphabet_;
+    Iterator curr_ = start_token_;
+    bool end_state_ = *ptr_ != 0;
+    std::size_t id_ = *(ptr_ + 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);
+            end_token_ = curr_;
+        }
+    }
+
+    if (end_state_)
+    {
+        // return longest match
+        start_token_ = end_token_;
+    }
+    else
+    {
+        id_ = npos;
+    }
+
+    return id_;
+}
+
+}}}}  // namespace boost::spirit::lex::static_
+
+#endif
Added: trunk/libs/spirit/example/lex/static_lexer/word_count_tokens.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/static_lexer/word_count_tokens.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,40 @@
+//  Copyright (c) 2001-2008 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(SPIRIT_LEXER_EXAMPLE_WORD_COUNT_TOKENS_FEB_10_2008_0739PM)
+#define SPIRIT_LEXER_EXAMPLE_WORD_COUNT_TOKENS_FEB_10_2008_0739PM
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition: We keep the base class for the token definition as a 
+//                    template parameter to allow this class to be used for
+//                    both: the code generation and the lexical analysis
+///////////////////////////////////////////////////////////////////////////////
+//[wc_static_tokenids
+enum tokenids 
+{
+    IDANY = boost::spirit::lex::min_token_id + 1,
+};
+//]
+
+//[wc_static_tokendef
+// This token definition class can be used without any change for all three
+// possible use cases: a dynamic lexical analyzer, a code generator, and a
+// static lexical analyzer.
+template <typename BaseLexer>
+struct word_count_tokens : boost::spirit::lex::lexer_def<BaseLexer> 
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define tokens and associate them with the lexer
+        word = "[^ \t\n]+";
+        self = word | '\n' | token_def<>(".", IDANY);
+    }
+    
+    boost::spirit::lex::token_def<std::string> word;
+};
+//]
+
+#endif
Added: trunk/libs/spirit/example/lex/strip_comments.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/strip_comments.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,164 @@
+//  Copyright (c) 2001-2008 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 is the equivalent to the following lex program:
+//
+//       %{
+//       /* INITIAL is the default start state.  COMMENT is our new  */
+//       /* state where we remove comments.                          */
+//       %}
+// 
+//       %s COMMENT
+//       %%
+//       <INITIAL>"//".*    ;
+//       <INITIAL>"/*"      BEGIN COMMENT; 
+//       <INITIAL>.         ECHO;
+//       <INITIAL>[\n]      ECHO;
+//       <COMMENT>"*/"      BEGIN INITIAL;
+//       <COMMENT>.         ;
+//       <COMMENT>[\n]      ;
+//       %%
+// 
+//       main() 
+//       {
+//         yylex();
+//       }
+//
+//  Its purpose is to strip comments out of C code.
+//
+//  Additionally this example demonstrates the use of lexer states to structure
+//  the lexer definition.
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_container.hpp>
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition: We use the lexertl based lexer engine as the underlying 
+//                    lexer type.
+///////////////////////////////////////////////////////////////////////////////
+enum tokenids 
+{
+    IDANY = lex::min_token_id + 10
+};
+
+template <typename Lexer>
+struct strip_comments_tokens : lexer_def<Lexer>
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define tokens and associate them with the lexer
+        cppcomment = "//.*\n";
+        ccomment = "/\\*";
+        endcomment = "\\*/";
+        
+        // The following tokens are associated with the default lexer state 
+        // (the "INITIAL" state). Specifying 'INITIAL' as a lexer state is 
+        // strictly optional.
+        self.add
+            (cppcomment)    // no explicit token id is associated
+            (ccomment)
+            (".", IDANY)    // IDANY is the token id associated with this token 
+                            // definition
+        ;
+        
+        // The following tokens are associated with the lexer state "COMMENT".
+        // We switch lexer states from inside the parsing process using the 
+        // in_state("COMMENT")[] parser component as shown below.
+        self("COMMENT").add
+            (endcomment)
+            (".", IDANY)
+        ;
+    }
+    
+    token_def<> cppcomment, ccomment, endcomment;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct strip_comments_grammar : grammar_def<Iterator>
+{
+    template <typename TokenDef>
+    strip_comments_grammar(TokenDef const& tok)
+    {
+        // The in_state("COMMENT")[...] parser component switches the lexer 
+        // state to be 'COMMENT' during the matching of the embedded parser.
+        start =  *(   tok.ccomment 
+                      >>  in_state("COMMENT") 
+                          [
+                              // the lexer is in the 'COMMENT' state during
+                              // matching of the following parser components
+                              *token(IDANY) >> tok.endcomment 
+                          ]
+                  |   tok.cppcomment
+                  |   token(IDANY)
+                  )
+              ;
+    }
+
+    rule<Iterator> start;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+    
+    // lexer type
+    typedef lexertl_lexer<lexertl_token<base_iterator_type> > lexer_type;
+    
+    // iterator type exposed by the lexer 
+    typedef 
+        lexer_iterator<strip_comments_tokens<lexer_type> >::type 
+    iterator_type;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    strip_comments_tokens<lexer_type> strip_comments;             // Our token definition
+    strip_comments_grammar<iterator_type> def (strip_comments);   // Our grammar definition
+
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    std::string str (read_from_file(1 == argc ? "strip_comments.input" : argv[1]));
+    base_iterator_type first = str.begin();
+    bool r = tokenize_and_parse(first, str.end(), make_lexer(strip_comments), 
+        make_parser(def));
+
+    if (r) {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+    }
+    else {
+        std::string rest(first, str.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;
+}
+
+
+
Added: trunk/libs/spirit/example/lex/strip_comments_lexer.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/strip_comments_lexer.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,121 @@
+//  Copyright (c) 2001-2008 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 is the equivalent to the following lex program:
+//
+//       %{
+//       /* INITIAL is the default start state.  COMMENT is our new  */
+//       /* state where we remove comments.                          */
+//       %}
+// 
+//       %s COMMENT
+//       %%
+//       <INITIAL>"//".*    ;
+//       <INITIAL>"/*"      BEGIN COMMENT; 
+//       <INITIAL>.         ECHO;
+//       <INITIAL>[\n]      ECHO;
+//       <COMMENT>"*/"      BEGIN INITIAL;
+//       <COMMENT>.         ;
+//       <COMMENT>[\n]      ;
+//       %%
+// 
+//       main() 
+//       {
+//         yylex();
+//       }
+//
+//  Its purpose is to strip comments out of C code.
+//
+//  Additionally this example demonstrates the use of lexer states to structure
+//  the lexer definition.
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/lex/lexer/lexer_actions.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;  
+using namespace boost::spirit::lex;
+  
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition: We use the lexertl based lexer engine as the underlying 
+//                    lexer type.
+///////////////////////////////////////////////////////////////////////////////
+enum tokenids 
+{
+    IDANY = lex::min_token_id + 10,
+    IDEOL = lex::min_token_id + 11
+};
+
+template <typename Lexer>
+struct strip_comments_tokens : lexer_def<Lexer>
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define tokens and associate them with the lexer
+        cppcomment = "//[^\n]*";
+        ccomment = "/\\*";
+        endcomment = "\\*/";
+        any = ".";
+        eol = "\n";
+        
+        // The following tokens are associated with the default lexer state 
+        // (the "INITIAL" state). Specifying 'INITIAL' as a lexer state is 
+        // strictly optional.
+        self =  cppcomment
+            |   ccomment    [ set_state("COMMENT") ]
+            |   eol         [ echo_input(std::cout) ]
+            |   any         [ echo_input(std::cout) ]
+            ;
+        
+        // The following tokens are associated with the lexer state 'COMMENT'.
+        self("COMMENT") 
+            =   endcomment  [ set_state("INITIAL") ]
+            |   eol
+            |   any 
+            ;
+    }
+    
+    token_def<> cppcomment, ccomment, endcomment, any, eol;
+};
+
+  ///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char* argv[])
+{
+    // iterator type used to expose the underlying input stream
+    typedef std::string::iterator base_iterator_type;
+    
+    // lexer type
+    typedef lexertl_actor_lexer<lexertl_token<base_iterator_type> > lexer_type;
+    
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    strip_comments_tokens<lexer_type> strip_comments;             // Our token definition
+
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input.
+    std::string str (read_from_file(1 == argc ? "strip_comments.input" : argv[1]));
+    base_iterator_type first = str.begin();
+    bool r = tokenize(first, str.end(), make_lexer(strip_comments));
+
+    if (!r) {
+        std::string rest(first, str.end());
+        std::cerr << "Lexical analysis failed\n" << "stopped at: \"" 
+                  << rest << "\"\n";
+    }
+    return 0;
+}
+
+
+
Added: trunk/libs/spirit/example/lex/word_count.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/word_count.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,172 @@
+//  Copyright (c) 2001-2008 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 is the equivalent to the following lex program:
+/*
+//[wcp_flex_version
+    %{
+        int c = 0, w = 0, l = 0;
+    %}
+    word   [^ \t\n]+
+    eol    \n	
+    %%
+    {word} { ++w; c += yyleng; }
+    {eol}  { ++c; ++l; }
+    .      { ++c; }
+    %%
+    main()
+    {
+	      yylex();
+	      printf("%d %d %d\n", l, w, c);
+    }
+//]
+*/
+//  Its purpose is to do the word count function of the wc command in UNIX. It 
+//  prints the number of lines, words and characters in a file. 
+//
+//  The example additionally demonstrates how to use the add_pattern(...)(...)
+//  syntax to define lexer patterns. These patterns are essentially parameter-
+//  less 'macros' for regular expressions, allowing to simplify their 
+//  definition.
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+#define BOOST_VARIANT_MINIMIZE_SIZE
+
+//[wcp_includes
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_container.hpp>
+//]
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+//[wcp_namespaces
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition: We use the lexertl based lexer engine as the underlying 
+//                    lexer type.
+///////////////////////////////////////////////////////////////////////////////
+//[wcp_token_ids
+enum tokenids 
+{
+    IDANY = lex::min_token_id + 10
+};
+//]
+
+//[wcp_token_definition
+template <typename Lexer>
+struct word_count_tokens : lexer_def<Lexer>
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define patterns (lexer macros) to be used during token definition 
+        // below
+        self.add_pattern
+            ("WORD", "[^ \t\n]+")
+        ;
+            
+        // define tokens and associate them with the lexer
+        word = "{WORD}";    // reference the pattern 'WORD' as defined above
+
+        // this lexer will recognize 3 token types: words, newlines, and 
+        // everything else
+        self.add
+            (word)          // no token id is needed here
+            ('\n')          // characters are usable as tokens as well
+            (".", IDANY)
+        ;
+    }
+    
+    token_def<std::string> word;
+};
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//  Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+//[wcp_grammar_definition
+template <typename Iterator>
+struct word_count_grammar : grammar_def<Iterator>
+{
+    template <typename TokenDef>
+    word_count_grammar(TokenDef const& tok)
+      : c(0), w(0), l(0)
+    {
+        using boost::phoenix::ref;
+        using boost::phoenix::size;
+        
+        // As documented in the Spirit.Qi documentation, any placeholders 
+        // (_1 et.al.) used in semantic actions inside a grammar need to be 
+        // imported from the namespace boost::spirit::arg_names, and not from 
+        // the corresponding namespace in Phoenix.
+        using boost::spirit::arg_names::_1;
+
+        start =  *(   tok.word      [++ref(w), ref(c) += size(_1)]
+                  |   char_('\n')   [++ref(c), ++ref(l)] 
+                  |   token(IDANY)  [++ref(c)]
+                  )
+              ;
+    }
+
+    std::size_t c, w, l;
+    rule<Iterator> start;
+};
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[wcp_main
+int main(int argc, char* argv[])
+{
+/*< define the token type to be used: `std::string` is available as the 
+     type of the token value 
+>*/  typedef lexertl_token<
+        char const*, boost::mpl::vector<std::string>
+    > token_type;
+
+/*< define the lexer type to use implementing the state machine
+>*/  typedef lexertl_lexer<token_type> lexer_type;
+
+/*< define the iterator type exposed by the lexer type
+>*/  typedef lexer_iterator<word_count_tokens<lexer_type> >::type iterator_type;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    word_count_tokens<lexer_type> word_count;            // Our token definition
+    word_count_grammar<iterator_type> def (word_count);  // Our grammar definition
+
+    // read in the file int memory
+    std::string str (read_from_file(1 == argc ? "word_count.input" : argv[1]));
+    char const* first = str.c_str();
+    char const* last = &first[str.size()];
+    
+    // Parsing is done based on the the token stream, not the character 
+    // stream read from the input. The function `tokenize_and_parse()` wraps
+    // the passed iterator range `[first, last)` by the lexical analyzer and 
+    // uses its exposed iterators to parse the toke stream.
+    bool r = tokenize_and_parse(first, last, make_lexer(word_count), 
+        make_parser(def));
+
+    if (r) {
+        std::cout << "lines: " << def.l << ", words: " << def.w 
+                  << ", characters: " << def.c << "\n";
+    }
+    else {
+        std::string rest(first, last);
+        std::cerr << "Parsing failed\n" << "stopped at: \"" 
+                  << rest << "\"\n";
+    }
+    return 0;
+}
+//]
Added: trunk/libs/spirit/example/lex/word_count_functor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/word_count_functor.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,184 @@
+//  Copyright (c) 2001-2008 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 is the equivalent to the following flex program:
+/*
+//[wcf_flex_version
+    %{
+        #define ID_WORD 1000
+        #define ID_EOL  1001
+        #define ID_CHAR 1002
+        int c = 0, w = 0, l = 0;
+    %}
+    %%
+    [^ \t\n]+  { return ID_WORD; }
+    \n         { return ID_EOL; }
+    .          { return ID_CHAR; }
+    %%
+    bool count(int tok)
+    {
+        switch (tok) {
+        case ID_WORD: ++w; c += yyleng; break;
+        case ID_EOL:  ++l; ++c; break;
+        case ID_CHAR: ++c; break;
+        default:
+            return false;
+        }
+        return true;
+    }
+    void main()
+    {
+        int tok = EOF;
+        do {
+            tok = yylex();
+            if (!count(tok))
+                break;
+        } while (EOF != tok);
+        printf("%d %d %d\n", l, w, c);
+    }
+//]
+*/
+//  Its purpose is to do the word count function of the wc command in UNIX. It 
+//  prints the number of lines, words and characters in a file. 
+//
+//  This examples shows how to use the tokenize() function together with a 
+//  simple functor, which gets executed whenever a token got matched in the 
+//  input sequence. 
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+//[wcf_includes
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
+//]
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+//[wcf_namespaces
+using namespace boost::spirit;
+using namespace boost::spirit::lex;
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token id definitions
+///////////////////////////////////////////////////////////////////////////////
+//[wcf_token_ids
+enum token_ids
+{
+    ID_WORD = 1000,
+    ID_EOL,
+    ID_CHAR
+};
+//]
+
+//[wcf_token_definition
+/*` The template `word_count_tokens` defines three different tokens: 
+    `ID_WORD`, `ID_EOL`, and `ID_CHAR`, representing a word (anything except 
+    a whitespace or a newline), a newline character, and any other character 
+    (`ID_WORD`, `ID_EOL`, and `ID_CHAR` are enum values representing the token 
+    ids, but could be anything else convertible to an integer as well).
+    The direct base class of any token definition class needs to be the 
+    template `lexer_def<>`, where the corresponding template parameter (here:
+    `lexertl_lexer<BaseIterator>`) defines which underlying lexer engine has 
+    to be used to provide the required state machine functionality. In this 
+    example we use the Lexertl based lexer engine as the underlying lexer type. 
+*/
+template <typename Lexer>
+struct word_count_tokens : lexer_def<Lexer>
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define tokens (the regular expression to match and the corresponding
+        // token id) and add them to the lexer 
+        self.add
+            ("[^ \t\n]+", ID_WORD) // words (anything except ' ', '\t' or '\n')
+            ("\n", ID_EOL)         // newline characters
+            (".", ID_CHAR)         // anything else is a plain character
+        ;
+    }
+};
+//]
+
+//[wcf_functor
+/*` In this example the struct 'counter' is used as a functor counting the 
+    characters, words and lines in the analyzed input sequence by identifying 
+    the matched tokens as passed from the /Spirit.Lex/ library. 
+*/
+struct counter
+{
+//<- this is an implementation detail and doesn't show up in the documentation
+    typedef bool result_type;
+    
+//->
+    // the function operator gets called for each of the matched tokens
+    // c, l, w are references to the counters used to keep track of the numbers
+    template <typename Token>
+    bool operator()(Token const& t, std::size_t& c, std::size_t& w, std::size_t& l) const
+    {
+        switch (t.id()) {
+        case ID_WORD:       // matched a word
+        // since we're using a default token type in this example, every 
+        // token instance contains a `iterator_range<BaseIterator>` as its 
+        // token value pointing to the matched character sequence in the input 
+            ++w; c += t.value().size(); 
+            break;
+        case ID_EOL:        // matched a newline character
+            ++l; ++c; 
+            break;
+        case ID_CHAR:       // matched something else
+            ++c; 
+            break;
+        }
+        return true;        // always continue to tokenize
+    }
+};
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[wcf_main
+/*` The main function simply loads the given file into memory (as a 
+    `std::string`), instantiates an instance of the token definition template
+    using the correct iterator type (`word_count_tokens<char const*>`),
+    and finally calls `lex::tokenize`, passing an instance of the counter functor
+    defined above. The return value of `lex::tokenize` will be `true` if the 
+    whole input sequence has been successfully tokenized, and `false` otherwise.
+*/
+int main(int argc, char* argv[])
+{
+    // these variables are used to count characters, words and lines
+    std::size_t c = 0, w = 0, l = 0;
+
+    // read input from the given file
+    std::string str (read_from_file(1 == argc ? "word_count.input" : argv[1]));
+
+    // create the token definition instance needed to invoke the lexical analyzer
+    word_count_tokens<lexertl_lexer<> > word_count_functor;
+
+    // tokenize the given string, the bound functor gets invoked for each of 
+    // the matched tokens
+    char const* first = str.c_str();
+    char const* last = &first[str.size()];
+    bool r = lex::tokenize(first, last, make_lexer(word_count_functor), 
+        boost::bind(counter(), _1, boost::ref(c), boost::ref(w), boost::ref(l)));
+
+    // print results
+    if (r) {
+        std::cout << "lines: " << l << ", words: " << w 
+                  << ", characters: " << c << "\n";
+    }
+    else {
+        std::string rest(first, last);
+        std::cout << "Lexical analysis failed\n" << "stopped at: \"" 
+                  << rest << "\"\n";
+    }
+    return 0;
+}
+//]
+
Added: trunk/libs/spirit/example/lex/word_count_functor_flex.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/word_count_functor_flex.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,1571 @@
+#line 2 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor_flex.cpp"
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#include <errno.h>
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else	/* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif	/* __STDC__ */
+#endif	/* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ * 	if ( condition_holds )
+ *		yyless( 5 );
+ *	else
+ *		do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		*yy_cp = yy_hold_char; \
+		YY_RESTORE_YY_MORE_OFFSET \
+		yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+		} \
+	while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+	{
+	FILE *yy_input_file;
+
+	char *yy_ch_buf;		/* input buffer */
+	char *yy_buf_pos;		/* current position in input buffer */
+
+	/* Size of input buffer in bytes, not including room for EOB
+	 * characters.
+	 */
+	yy_size_t yy_buf_size;
+
+	/* Number of characters read into yy_ch_buf, not including EOB
+	 * characters.
+	 */
+	int yy_n_chars;
+
+	/* Whether we "own" the buffer - i.e., we know we created it,
+	 * and can realloc() it to grow it, and should free() it to
+	 * delete it.
+	 */
+	int yy_is_our_buffer;
+
+	/* Whether this is an "interactive" input source; if so, and
+	 * if we're using stdio for input, then we want to use getc()
+	 * instead of fread(), to make sure we stop fetching input after
+	 * each newline.
+	 */
+	int yy_is_interactive;
+
+	/* Whether we're considered to be at the beginning of a line.
+	 * If so, '^' rules will be active on the next match, otherwise
+	 * not.
+	 */
+	int yy_at_bol;
+
+	/* Whether to try to fill the input buffer when we reach the
+	 * end of it.
+	 */
+	int yy_fill_buffer;
+
+	int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+	/* When an EOF's been seen but there's still some text to process
+	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+	 * shouldn't try reading from the input source any more.  We might
+	 * still have a bunch of tokens to match, though, because of
+	 * possible backing-up.
+	 *
+	 * When we actually see the EOF, we change the status to "new"
+	 * (via yyrestart()), so that the user can continue scanning by
+	 * just pointing yyin at a new input file.
+	 */
+#define YY_BUFFER_EOF_PENDING 2
+	};
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;		/* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;		/* whether we need to initialize */
+static int yy_start = 0;	/* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_is_interactive = is_interactive; \
+	}
+
+#define yy_set_bol(at_bol) \
+	{ \
+	if ( ! yy_current_buffer ) \
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+	yy_current_buffer->yy_at_bol = at_bol; \
+	}
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+	yytext_ptr = yy_bp; \
+	yyleng = (int) (yy_cp - yy_bp); \
+	yy_hold_char = *yy_cp; \
+	*yy_cp = '\0'; \
+	yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 4
+#define YY_END_OF_BUFFER 5
+static yyconst short int yy_accept[9] =
+    {   0,
+        0,    0,    5,    1,    3,    2,    1,    0
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[4] =
+    {   0,
+        1,    2,    2
+    } ;
+
+static yyconst short int yy_base[10] =
+    {   0,
+        0,    0,    5,    0,    6,    6,    0,    6,    3
+    } ;
+
+static yyconst short int yy_def[10] =
+    {   0,
+        8,    1,    8,    9,    8,    8,    9,    0,    8
+    } ;
+
+static yyconst short int yy_nxt[10] =
+    {   0,
+        4,    5,    6,    7,    8,    3,    8,    8,    8
+    } ;
+
+static yyconst short int yy_chk[10] =
+    {   0,
+        1,    1,    1,    9,    3,    8,    8,    8,    8
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+#define INITIAL 0
+#line 2 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+#include <boost/timer.hpp>
+#if defined(_WIN32)
+    #include <io.h>
+#endif
+    #define ID_WORD 1000
+    #define ID_EOL  1001
+    #define ID_CHAR 1002
+#line 375 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor_flex.cpp"
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+	if ( yy_current_buffer->yy_is_interactive ) \
+		{ \
+		int c = '*', n; \
+		for ( n = 0; n < max_size && \
+			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+			buf[n] = (char) c; \
+		if ( c == '\n' ) \
+			buf[n++] = (char) c; \
+		if ( c == EOF && ferror( yyin ) ) \
+			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+		result = n; \
+		} \
+	else \
+		{ \
+		errno=0; \
+		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+			{ \
+			if( errno != EINTR) \
+				{ \
+				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+				break; \
+				} \
+			errno=0; \
+			clearerr(yyin); \
+			} \
+		}
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+	YY_USER_ACTION
+
+YY_DECL
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp, *yy_bp;
+	register int yy_act;
+
+#line 11 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+
+#line 539 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor_flex.cpp"
+
+	if ( yy_init )
+		{
+		yy_init = 0;
+
+#ifdef YY_USER_INIT
+		YY_USER_INIT;
+#endif
+
+		if ( ! yy_start )
+			yy_start = 1;	/* first start state */
+
+		if ( ! yyin )
+			yyin = stdin;
+
+		if ( ! yyout )
+			yyout = stdout;
+
+		if ( ! yy_current_buffer )
+			yy_current_buffer =
+				yy_create_buffer( yyin, YY_BUF_SIZE );
+
+		yy_load_buffer_state();
+		}
+
+	while ( 1 )		/* loops until end-of-file is reached */
+		{
+		yy_cp = yy_c_buf_p;
+
+		/* Support of yytext. */
+		*yy_cp = yy_hold_char;
+
+		/* yy_bp points to the position in yy_ch_buf of the start of
+		 * the current run.
+		 */
+		yy_bp = yy_cp;
+
+		yy_current_state = yy_start;
+yy_match:
+		do
+			{
+			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+			if ( yy_accept[yy_current_state] )
+				{
+				yy_last_accepting_state = yy_current_state;
+				yy_last_accepting_cpos = yy_cp;
+				}
+			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+				{
+				yy_current_state = (int) yy_def[yy_current_state];
+				if ( yy_current_state >= 9 )
+					yy_c = yy_meta[(unsigned int) yy_c];
+				}
+			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+			++yy_cp;
+			}
+		while ( yy_base[yy_current_state] != 6 );
+
+yy_find_action:
+		yy_act = yy_accept[yy_current_state];
+		if ( yy_act == 0 )
+			{ /* have to back up */
+			yy_cp = yy_last_accepting_cpos;
+			yy_current_state = yy_last_accepting_state;
+			yy_act = yy_accept[yy_current_state];
+			}
+
+		YY_DO_BEFORE_ACTION;
+
+
+do_action:	/* This label is used only to access EOF actions. */
+
+
+		switch ( yy_act )
+	{ /* beginning of action switch */
+			case 0: /* must back up */
+			/* undo the effects of YY_DO_BEFORE_ACTION */
+			*yy_cp = yy_hold_char;
+			yy_cp = yy_last_accepting_cpos;
+			yy_current_state = yy_last_accepting_state;
+			goto yy_find_action;
+
+case 1:
+YY_RULE_SETUP
+#line 12 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+{ return ID_WORD; }
+	YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 13 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+{ return ID_EOL; }
+	YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 14 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+{ return ID_CHAR; }
+	YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 15 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+ECHO;
+	YY_BREAK
+#line 642 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor_flex.cpp"
+case YY_STATE_EOF(INITIAL):
+	yyterminate();
+
+	case YY_END_OF_BUFFER:
+		{
+		/* Amount of text matched not including the EOB char. */
+		int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+		*yy_cp = yy_hold_char;
+		YY_RESTORE_YY_MORE_OFFSET
+
+		if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+			{
+			/* We're scanning a new file or input source.  It's
+			 * possible that this happened because the user
+			 * just pointed yyin at a new source and called
+			 * yylex().  If so, then we have to assure
+			 * consistency between yy_current_buffer and our
+			 * globals.  Here is the right place to do so, because
+			 * this is the first action (other than possibly a
+			 * back-up) that will match for the new input source.
+			 */
+			yy_n_chars = yy_current_buffer->yy_n_chars;
+			yy_current_buffer->yy_input_file = yyin;
+			yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+			}
+
+		/* Note that here we test for yy_c_buf_p "<=" to the position
+		 * of the first EOB in the buffer, since yy_c_buf_p will
+		 * already have been incremented past the NUL character
+		 * (since all states make transitions on EOB to the
+		 * end-of-buffer state).  Contrast this with the test
+		 * in input().
+		 */
+		if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			{ /* This was really a NUL. */
+			yy_state_type yy_next_state;
+
+			yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+			yy_current_state = yy_get_previous_state();
+
+			/* Okay, we're now positioned to make the NUL
+			 * transition.  We couldn't have
+			 * yy_get_previous_state() go ahead and do it
+			 * for us because it doesn't know how to deal
+			 * with the possibility of jamming (and we don't
+			 * want to build jamming into it because then it
+			 * will run more slowly).
+			 */
+
+			yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+			yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+			if ( yy_next_state )
+				{
+				/* Consume the NUL. */
+				yy_cp = ++yy_c_buf_p;
+				yy_current_state = yy_next_state;
+				goto yy_match;
+				}
+
+			else
+				{
+				yy_cp = yy_c_buf_p;
+				goto yy_find_action;
+				}
+			}
+
+		else switch ( yy_get_next_buffer() )
+			{
+			case EOB_ACT_END_OF_FILE:
+				{
+				yy_did_buffer_switch_on_eof = 0;
+
+				if ( yywrap() )
+					{
+					/* Note: because we've taken care in
+					 * yy_get_next_buffer() to have set up
+					 * yytext, we can now set up
+					 * yy_c_buf_p so that if some total
+					 * hoser (like flex itself) wants to
+					 * call the scanner after we return the
+					 * YY_NULL, it'll still work - another
+					 * YY_NULL will get returned.
+					 */
+					yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+					yy_act = YY_STATE_EOF(YY_START);
+					goto do_action;
+					}
+
+				else
+					{
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+					}
+				break;
+				}
+
+			case EOB_ACT_CONTINUE_SCAN:
+				yy_c_buf_p =
+					yytext_ptr + yy_amount_of_matched_text;
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_match;
+
+			case EOB_ACT_LAST_MATCH:
+				yy_c_buf_p =
+				&yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+				yy_current_state = yy_get_previous_state();
+
+				yy_cp = yy_c_buf_p;
+				yy_bp = yytext_ptr + YY_MORE_ADJ;
+				goto yy_find_action;
+			}
+		break;
+		}
+
+	default:
+		YY_FATAL_ERROR(
+			"fatal flex scanner internal error--no action found" );
+	} /* end of action switch */
+		} /* end of scanning one token */
+	} /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *	EOB_ACT_LAST_MATCH -
+ *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *	EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+	{
+	register char *dest = yy_current_buffer->yy_ch_buf;
+	register char *source = yytext_ptr;
+	register int number_to_move, i;
+	int ret_val;
+
+	if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+		YY_FATAL_ERROR(
+		"fatal flex scanner internal error--end of buffer missed" );
+
+	if ( yy_current_buffer->yy_fill_buffer == 0 )
+		{ /* Don't try to fill the buffer, so this is an EOF. */
+		if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+			{
+			/* We matched a single character, the EOB, so
+			 * treat this as a final EOF.
+			 */
+			return EOB_ACT_END_OF_FILE;
+			}
+
+		else
+			{
+			/* We matched some text prior to the EOB, first
+			 * process it.
+			 */
+			return EOB_ACT_LAST_MATCH;
+			}
+		}
+
+	/* Try to read more data. */
+
+	/* First move last chars to start of buffer. */
+	number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+	for ( i = 0; i < number_to_move; ++i )
+		*(dest++) = *(source++);
+
+	if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+		/* don't do the read, it's not guaranteed to return an EOF,
+		 * just force an EOF
+		 */
+		yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+	else
+		{
+		int num_to_read =
+			yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+		while ( num_to_read <= 0 )
+			{ /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+			YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+			/* just a shorter name for the current buffer */
+			YY_BUFFER_STATE b = yy_current_buffer;
+
+			int yy_c_buf_p_offset =
+				(int) (yy_c_buf_p - b->yy_ch_buf);
+
+			if ( b->yy_is_our_buffer )
+				{
+				int new_size = b->yy_buf_size * 2;
+
+				if ( new_size <= 0 )
+					b->yy_buf_size += b->yy_buf_size / 8;
+				else
+					b->yy_buf_size *= 2;
+
+				b->yy_ch_buf = (char *)
+					/* Include room in for 2 EOB chars. */
+					yy_flex_realloc( (void *) b->yy_ch_buf,
+							 b->yy_buf_size + 2 );
+				}
+			else
+				/* Can't grow it, we don't own it. */
+				b->yy_ch_buf = 0;
+
+			if ( ! b->yy_ch_buf )
+				YY_FATAL_ERROR(
+				"fatal error - scanner input buffer overflow" );
+
+			yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+			num_to_read = yy_current_buffer->yy_buf_size -
+						number_to_move - 1;
+#endif
+			}
+
+		if ( num_to_read > YY_READ_BUF_SIZE )
+			num_to_read = YY_READ_BUF_SIZE;
+
+		/* Read in more data. */
+		YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+			yy_n_chars, num_to_read );
+
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	if ( yy_n_chars == 0 )
+		{
+		if ( number_to_move == YY_MORE_ADJ )
+			{
+			ret_val = EOB_ACT_END_OF_FILE;
+			yyrestart( yyin );
+			}
+
+		else
+			{
+			ret_val = EOB_ACT_LAST_MATCH;
+			yy_current_buffer->yy_buffer_status =
+				YY_BUFFER_EOF_PENDING;
+			}
+		}
+
+	else
+		ret_val = EOB_ACT_CONTINUE_SCAN;
+
+	yy_n_chars += number_to_move;
+	yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+	yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+	yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+	return ret_val;
+	}
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+	{
+	register yy_state_type yy_current_state;
+	register char *yy_cp;
+
+	yy_current_state = yy_start;
+
+	for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+		{
+		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+		if ( yy_accept[yy_current_state] )
+			{
+			yy_last_accepting_state = yy_current_state;
+			yy_last_accepting_cpos = yy_cp;
+			}
+		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+			{
+			yy_current_state = (int) yy_def[yy_current_state];
+			if ( yy_current_state >= 9 )
+				yy_c = yy_meta[(unsigned int) yy_c];
+			}
+		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+		}
+
+	return yy_current_state;
+	}
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *	next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+	{
+	register int yy_is_jam;
+	register char *yy_cp = yy_c_buf_p;
+
+	register YY_CHAR yy_c = 1;
+	if ( yy_accept[yy_current_state] )
+		{
+		yy_last_accepting_state = yy_current_state;
+		yy_last_accepting_cpos = yy_cp;
+		}
+	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+		{
+		yy_current_state = (int) yy_def[yy_current_state];
+		if ( yy_current_state >= 9 )
+			yy_c = yy_meta[(unsigned int) yy_c];
+		}
+	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+	yy_is_jam = (yy_current_state == 8);
+
+	return yy_is_jam ? 0 : yy_current_state;
+	}
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+	{
+	register char *yy_cp = yy_c_buf_p;
+
+	/* undo effects of setting up yytext */
+	*yy_cp = yy_hold_char;
+
+	if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+		{ /* need to shift things up to make room */
+		/* +2 for EOB chars. */
+		register int number_to_move = yy_n_chars + 2;
+		register char *dest = &yy_current_buffer->yy_ch_buf[
+					yy_current_buffer->yy_buf_size + 2];
+		register char *source =
+				&yy_current_buffer->yy_ch_buf[number_to_move];
+
+		while ( source > yy_current_buffer->yy_ch_buf )
+			*--dest = *--source;
+
+		yy_cp += (int) (dest - source);
+		yy_bp += (int) (dest - source);
+		yy_current_buffer->yy_n_chars =
+			yy_n_chars = yy_current_buffer->yy_buf_size;
+
+		if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+		}
+
+	*--yy_cp = (char) c;
+
+
+	yytext_ptr = yy_bp;
+	yy_hold_char = *yy_cp;
+	yy_c_buf_p = yy_cp;
+	}
+#endif	/* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+	{
+	int c;
+
+	*yy_c_buf_p = yy_hold_char;
+
+	if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+		{
+		/* yy_c_buf_p now points to the character we want to return.
+		 * If this occurs *before* the EOB characters, then it's a
+		 * valid NUL; if not, then we've hit the end of the buffer.
+		 */
+		if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+			/* This was really a NUL. */
+			*yy_c_buf_p = '\0';
+
+		else
+			{ /* need more input */
+			int offset = yy_c_buf_p - yytext_ptr;
+			++yy_c_buf_p;
+
+			switch ( yy_get_next_buffer() )
+				{
+				case EOB_ACT_LAST_MATCH:
+					/* This happens because yy_g_n_b()
+					 * sees that we've accumulated a
+					 * token and flags that we need to
+					 * try matching the token before
+					 * proceeding.  But for input(),
+					 * there's no matching to consider.
+					 * So convert the EOB_ACT_LAST_MATCH
+					 * to EOB_ACT_END_OF_FILE.
+					 */
+
+					/* Reset buffer status. */
+					yyrestart( yyin );
+
+					/* fall through */
+
+				case EOB_ACT_END_OF_FILE:
+					{
+					if ( yywrap() )
+						return EOF;
+
+					if ( ! yy_did_buffer_switch_on_eof )
+						YY_NEW_FILE;
+#ifdef __cplusplus
+					return yyinput();
+#else
+					return input();
+#endif
+					}
+
+				case EOB_ACT_CONTINUE_SCAN:
+					yy_c_buf_p = yytext_ptr + offset;
+					break;
+				}
+			}
+		}
+
+	c = *(unsigned char *) yy_c_buf_p;	/* cast for 8-bit char's */
+	*yy_c_buf_p = '\0';	/* preserve yytext */
+	yy_hold_char = *++yy_c_buf_p;
+
+
+	return c;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+	{
+	if ( ! yy_current_buffer )
+		yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+	yy_init_buffer( yy_current_buffer, input_file );
+	yy_load_buffer_state();
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+	{
+	if ( yy_current_buffer == new_buffer )
+		return;
+
+	if ( yy_current_buffer )
+		{
+		/* Flush out information for old buffer. */
+		*yy_c_buf_p = yy_hold_char;
+		yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+		yy_current_buffer->yy_n_chars = yy_n_chars;
+		}
+
+	yy_current_buffer = new_buffer;
+	yy_load_buffer_state();
+
+	/* We don't actually know whether we did this switch during
+	 * EOF (yywrap()) processing, but the only time this flag
+	 * is looked at is after yywrap() is called, so it's safe
+	 * to go ahead and always set it.
+	 */
+	yy_did_buffer_switch_on_eof = 1;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+	{
+	yy_n_chars = yy_current_buffer->yy_n_chars;
+	yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+	yyin = yy_current_buffer->yy_input_file;
+	yy_hold_char = *yy_c_buf_p;
+	}
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_buf_size = size;
+
+	/* yy_ch_buf has to be 2 characters longer than the size given because
+	 * we need to put in 2 end-of-buffer characters.
+	 */
+	b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+	if ( ! b->yy_ch_buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+	b->yy_is_our_buffer = 1;
+
+	yy_init_buffer( b, file );
+
+	return b;
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+	{
+	if ( ! b )
+		return;
+
+	if ( b == yy_current_buffer )
+		yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+	if ( b->yy_is_our_buffer )
+		yy_flex_free( (void *) b->yy_ch_buf );
+
+	yy_flex_free( (void *) b );
+	}
+
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+	{
+	yy_flush_buffer( b );
+
+	b->yy_input_file = file;
+	b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+	b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+	b->yy_is_interactive = 0;
+#else
+	b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+	}
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+	{
+	if ( ! b )
+		return;
+
+	b->yy_n_chars = 0;
+
+	/* We always need two end-of-buffer characters.  The first causes
+	 * a transition to the end-of-buffer state.  The second causes
+	 * a jam in that state.
+	 */
+	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+	b->yy_buf_pos = &b->yy_ch_buf[0];
+
+	b->yy_at_bol = 1;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	if ( b == yy_current_buffer )
+		yy_load_buffer_state();
+	}
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+	{
+	YY_BUFFER_STATE b;
+
+	if ( size < 2 ||
+	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+		/* They forgot to leave room for the EOB's. */
+		return 0;
+
+	b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+	if ( ! b )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+	b->yy_buf_pos = b->yy_ch_buf = base;
+	b->yy_is_our_buffer = 0;
+	b->yy_input_file = 0;
+	b->yy_n_chars = b->yy_buf_size;
+	b->yy_is_interactive = 0;
+	b->yy_at_bol = 1;
+	b->yy_fill_buffer = 0;
+	b->yy_buffer_status = YY_BUFFER_NEW;
+
+	yy_switch_to_buffer( b );
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+	{
+	int len;
+	for ( len = 0; yy_str[len]; ++len )
+		;
+
+	return yy_scan_bytes( yy_str, len );
+	}
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+	{
+	YY_BUFFER_STATE b;
+	char *buf;
+	yy_size_t n;
+	int i;
+
+	/* Get memory for full buffer, including space for trailing EOB's. */
+	n = len + 2;
+	buf = (char *) yy_flex_alloc( n );
+	if ( ! buf )
+		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+	for ( i = 0; i < len; ++i )
+		buf[i] = bytes[i];
+
+	buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+	b = yy_scan_buffer( buf, n );
+	if ( ! b )
+		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+	/* It's okay to grow etc. this buffer, and we should throw it
+	 * away when we're done.
+	 */
+	b->yy_is_our_buffer = 1;
+
+	return b;
+	}
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+	{
+	if ( yy_start_stack_ptr >= yy_start_stack_depth )
+		{
+		yy_size_t new_size;
+
+		yy_start_stack_depth += YY_START_STACK_INCR;
+		new_size = yy_start_stack_depth * sizeof( int );
+
+		if ( ! yy_start_stack )
+			yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+		else
+			yy_start_stack = (int *) yy_flex_realloc(
+					(void *) yy_start_stack, new_size );
+
+		if ( ! yy_start_stack )
+			YY_FATAL_ERROR(
+			"out of memory expanding start-condition stack" );
+		}
+
+	yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+	BEGIN(new_state);
+	}
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+	{
+	if ( --yy_start_stack_ptr < 0 )
+		YY_FATAL_ERROR( "start-condition stack underflow" );
+
+	BEGIN(yy_start_stack[yy_start_stack_ptr]);
+	}
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+	{
+	return yy_start_stack[yy_start_stack_ptr - 1];
+	}
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+	{
+	(void) fprintf( stderr, "%s\n", msg );
+	exit( YY_EXIT_FAILURE );
+	}
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+	do \
+		{ \
+		/* Undo effects of setting up yytext. */ \
+		yytext[yyleng] = yy_hold_char; \
+		yy_c_buf_p = yytext + n; \
+		yy_hold_char = *yy_c_buf_p; \
+		*yy_c_buf_p = '\0'; \
+		yyleng = n; \
+		} \
+	while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+	{
+	register int i;
+	for ( i = 0; i < n; ++i )
+		s1[i] = s2[i];
+	}
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+	{
+	register int n;
+	for ( n = 0; s[n]; ++n )
+		;
+
+	return n;
+	}
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+	{
+	return (void *) malloc( size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+	{
+	/* The cast to (char *) in the following accommodates both
+	 * implementations that use char* generic pointers, and those
+	 * that use void* generic pointers.  It works with the latter
+	 * because both ANSI C and C++ allow castless assignment from
+	 * any pointer type to void*, and deal with argument conversions
+	 * as though doing an assignment.
+	 */
+	return (void *) realloc( (char *) ptr, size );
+	}
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+	{
+	free( ptr );
+	}
+
+#if YY_MAIN
+int main()
+	{
+	yylex();
+	return 0;
+	}
+#endif
+#line 15 "c:\\CVS\\spirit\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+
+
+bool count(int tok, int* c, int* w, int* l)
+{
+    switch (tok) {
+    case ID_WORD: ++*w; *c += yyleng; break;
+    case ID_EOL:  ++*l; ++*c; break;
+    case ID_CHAR: ++*c; break;
+    default:
+        return false;
+    }
+    return true;
+}
+
+void main(int argc, char* argv[])
+{
+    int tok = EOF;
+    int c = 0, w = 0, l = 0;
+    yyin = fopen(1 == argc ? "word_count.input" : argv[1], "r");
+    if (NULL == yyin) {
+        fprintf(stderr, "Couldn't open input file!\n");
+        exit(-1); 
+    }
+
+    boost::timer tim;
+    do {
+        tok = yylex();
+        if (!count(tok, &c, &w, &l))
+            break;
+    } while (EOF != tok);
+    printf("lines: %d, words: %d, characters: %d\n", l, w, c);
+	printf("Time elapsed: %f", tim.elapsed());
+    fclose(yyin);
+}
+
+extern "C" int yywrap()  
+{
+    return 1;
+}
+
Added: trunk/libs/spirit/example/lex/word_count_lexer.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/lex/word_count_lexer.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,138 @@
+//  Copyright (c) 2001-2008 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 is the equivalent to the following lex program:
+/*
+//[wcl_flex_version
+    %{
+        int c = 0, w = 0, l = 0;
+    %}
+    %%
+    [^ \t\n]+  { ++w; c += yyleng; }
+    \n         { ++c; ++l; }
+    .          { ++c; }
+    %%
+    main()
+    {
+        yylex();
+        printf("%d %d %d\n", l, w, c);
+    }
+//]
+*/
+//  Its purpose is to do the word count function of the wc command in UNIX. It 
+//  prints the number of lines, words and characters in a file. 
+//
+//  This examples shows how to use semantic actions associated with token 
+//  definitions to directly attach actions to tokens. These get executed 
+//  whenever the corresponding token got matched in the input sequence. Note,
+//  how this example implements all functionality directly in the lexer 
+//  definition without any need for a parser.
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+//[wcl_includes
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_algorithm.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+//]
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+//[wcl_namespaces
+using namespace boost::spirit;
+using namespace boost::spirit::lex;
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition: We use the lexertl based lexer engine as the underlying 
+//                    lexer type.
+//
+//  Note, the token definition type is derived from the 'lexertl_actor_lexer'
+//  template, which is a necessary to being able to use lexer semantic actions.
+///////////////////////////////////////////////////////////////////////////////
+//[wcl_token_definition
+template <typename Lexer>
+struct word_count_tokens : lexer_def<Lexer>
+{
+    word_count_tokens()
+      : c(0), w(0), l(0),
+        word("[^ \t\n]+"), eol("\n"), any(".")  // define tokens
+    {}
+    
+    template <typename Self>
+    void def (Self& self)
+    {
+        using boost::phoenix::ref;
+        using boost::phoenix::distance;
+        
+        // Note that all placeholders used in lexer semantic actions in 
+        // conjunction with functors created based on Phoenix2 need to be from 
+        // the namespace boost::phoenix::arg_names (not spirit::arg_names). 
+        // Using the wrong placeholders leads to subtle compilation errors 
+        // which are difficult to backtrack to their cause.
+        using boost::phoenix::arg_names::_1;
+
+        // associate tokens with the lexer
+        self =  word  [++ref(w), ref(c) += distance(_1)]
+            |   eol   [++ref(c), ++ref(l)] 
+            |   any   [++ref(c)]
+            ;
+    }
+    
+    std::size_t c, w, l;
+    token_def<> word, eol, any;
+};
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[wcl_main
+int main(int argc, char* argv[])
+{
+    // read input from the given file
+    std::string str (read_from_file(1 == argc ? "word_count.input" : argv[1]));
+
+    // Specifying 'omitted' as the token value type generates a token class not
+    // holding any token value at all (not even the iterator_range of the 
+    // matched input sequence), therefor optimizing the token, the lexer, and 
+    // possibly the parser implementation as much as possible. 
+    //
+    // Specifying mpl::false_ as the 3rd template parameter generates a token
+    // type and an iterator, both holding no lexer state, allowing for even more 
+    // aggressive optimizations.
+    //
+    // As a result the token instances contain the token ids as the only data 
+    // member.
+    typedef lexertl_token<char const*, omitted, boost::mpl::false_> token_type;
+
+    // lexer type
+    typedef lexertl_actor_lexer<token_type> lexer_type;
+    
+    // create the lexer object instance needed to invoke the lexical analysis 
+    word_count_tokens<lexer_type> word_count_lexer;
+
+    // tokenize the given string, all generated tokens are discarded
+    char const* first = str.c_str();
+    char const* last = &first[str.size()];
+    bool r = tokenize(first, last, make_lexer(word_count_lexer));
+
+    if (r) {
+        std::cout << "lines: " << word_count_lexer.l 
+                  << ", words: " << word_count_lexer.w 
+                  << ", characters: " << word_count_lexer.c 
+                  << "\n";
+    }
+    else {
+        std::string rest(first, last);
+        std::cout << "Lexical analysis failed\n" << "stopped at: \"" 
+                  << rest << "\"\n";
+    }
+    return 0;
+}
+//]
Added: trunk/libs/spirit/example/qi/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/Jamfile	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,46 @@
+#==============================================================================
+#   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 ;
+
+exe sum : sum.cpp ;
+exe complex_number : complex_number.cpp ;
+exe employee : employee.cpp ;
+exe roman : roman.cpp ;
+exe mini_xml1 : mini_xml1.cpp ;
+exe mini_xml2 : mini_xml2.cpp ;
+exe num_list : num_list.cpp ;
+exe num_list2 : num_list2.cpp ;
+exe num_list3 : num_list3.cpp ;
+
+exe calc1 : calc1.cpp ;
+exe calc2 : calc2.cpp ;
+exe calc3 : calc3.cpp ;
+exe calc4 : calc4.cpp ;
+exe calc5 : calc5.cpp ;
+
+exe calc6 :
+    calc6/calc6.cpp
+    calc6/calc6a.cpp
+    calc6/calc6b.cpp
+    calc6/calc6c.cpp
+    ;
+
+exe calc7 :
+    calc7/calc7.cpp
+    calc7/calc7a.cpp
+    calc7/calc7b.cpp
+    calc7/calc7c.cpp
+    ;
+
+exe mini_c :
+    mini_c/mini_c.cpp
+    mini_c/mini_ca.cpp
+    mini_c/mini_cb.cpp
+    mini_c/mini_cc.cpp
+    mini_c/mini_cd.cpp
+    ;
+
Added: trunk/libs/spirit/example/qi/calc1.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc1.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,104 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <iostream>
+#include <string>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our calculator grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator : grammar_def<Iterator, space_type>
+{
+    calculator()
+    {
+        expression =
+            term
+            >> *(   ('+' >> term)
+                |   ('-' >> term)
+                )
+            ;
+
+        term =
+            factor
+            >> *(   ('*' >> factor)
+                |   ('/' >> factor)
+                )
+            ;
+
+        factor =
+            uint_
+            |   '(' >> expression >> ')'
+            |   ('-' >> factor)
+            |   ('+' >> factor)
+            ;
+    }
+
+    rule<Iterator, 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 calculator<iterator_type> calculator;
+
+    calculator def; //  Our grammar definition
+    grammar<calculator> calc(def, def.expression); // 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;
+}
+
+
Added: trunk/libs/spirit/example/qi/calc2.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc2.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,123 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  A Calculator example demonstrating the grammar and semantic actions
+//  using phoenix to "bind" plain functions. The parser prints code suitable
+//  for a stack based virtual machine.
+//
+//  [ JDG May 10, 2002 ]    spirit1
+//  [ JDG March 4, 2007 ]   spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_bind.hpp>
+
+#include <iostream>
+#include <string>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::bind;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Semantic actions
+///////////////////////////////////////////////////////////////////////////////
+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 : grammar_def<Iterator, space_type>
+{
+    calculator()
+    {
+        expression =
+            term
+            >> *(   ('+' >> term            [bind(&do_add)])
+                |   ('-' >> term            [bind(&do_subt)])
+                )
+            ;
+
+        term =
+            factor
+            >> *(   ('*' >> factor          [bind(&do_mult)])
+                |   ('/' >> factor          [bind(&do_div)])
+                )
+            ;
+
+        factor =
+            uint_                           [bind(&do_int, _1)]
+            |   '(' >> expression >> ')'
+            |   ('-' >> factor              [bind(&do_neg)])
+            |   ('+' >> factor)
+            ;
+    }
+
+    rule<Iterator, 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 calculator<iterator_type> calculator;
+
+    calculator def; //  Our grammar definition
+    grammar<calculator> calc(def, def.expression); // 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;
+}
+
+
Added: trunk/libs/spirit/example/qi/calc3.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc3.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,110 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our calculator grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator : grammar_def<Iterator, int(), space_type>
+{
+    calculator()
+    {
+        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])
+            ;
+    }
+
+    rule<Iterator, int(), 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 calculator<iterator_type> calculator;
+
+    calculator def; //  Our grammar definition
+    grammar<calculator> calc(def, def.expression); // 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, result, space);
+
+        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;
+}
+
+
Added: trunk/libs/spirit/example/qi/calc3_lexer.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc3_lexer.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,201 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2008 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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.
+//
+//  Additionally this examples shows how to build and use a lexer based on 
+//  Ben Hansons Lexertl (http://www.benhanson.net/lexertl.html). This way the
+//  parser matches the grammar against the tokens generated by the lexer 
+//  component and not against the input character stream.
+//
+//  Even if the benefits of using a lexer for this small calculator grammar may 
+//  not outweight the corresponding overhead, we provide this example because 
+//  it allows to concentrate on the essentials without having to understand
+//  the semantics first.
+//
+//  [ JDG June 29, 2002 ]   spirit1
+//  [ JDG March 5, 2007 ]   spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::lex;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our token definition
+//  This class is used to define all the tokens to be recognized by the lexer. 
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct calculator_tokens : lexer_def<Lexer>
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        // unsigned integer token definition
+        ui = "[1-9][0-9]*";
+        
+        // whitespace token definitions
+        ws = "[ \\t\\f\\v]+";
+        c_comment = "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/";
+        
+        // build token set
+        skipper = ws | c_comment;                   // += is allowed as well
+        
+        // associate the tokens and the token set with the lexer
+        // default lexer state
+        self = token_def<>('+') | '-' | '*' | '/' | '(' | ')'; 
+        self += ui;                                 // still default state
+        
+        // The token_set 'skipper' get's assigned to a separate lexer state
+        // which allows to use it separately from the main tokenization
+        // (it is used as the skipper parser below)
+        self("SKIPPER") = skipper;                  // lexer state "SKIPPER"
+    }
+
+    // This are the tokens to be recognized by the lexer.
+    token_def<unsigned int> ui;   // matched tokens will have a unsigned int 
+    token_def<> ws, c_comment;    // attribute will not be used
+
+    // This is the only token set explicitly defined by this lexer because it
+    // needs to be accessible from the outside (used as skip parser below).
+    typename Lexer::token_set skipper;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our calculator grammar
+//
+//  The difference to the original example (calc3.cpp) is that we are 
+//  specifying a second template parameter referring to the lexer. Further, we 
+//  use a defined tokenset from above as the skip parser.
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct calculator : grammar_def<Iterator, int(), typename Lexer::token_set>
+{
+    template <typename TokenDef>
+    calculator(TokenDef const& tok)
+    {
+        // grammar
+        expression =
+            term                            [_val = _1]
+            >> *(   ('+' >> term            [_val += _1])
+                |   ('-' >> term            [_val -= _1])
+                )
+            ;
+
+        term =
+            factor                          [_val = _1]
+            >> *(   ('*' >> factor          [_val *= _1])
+                |   ('/' >> factor          [_val /= _1])
+                )
+            ;
+
+        factor =
+            tok.ui                          [_val = _1]
+            |   '(' >> expression           [_val = _1] >> ')'
+            |   ('-' >> factor              [_val = -_1])
+            |   ('+' >> factor              [_val = _1])
+            ;
+    }
+
+    rule<Iterator, int(), typename Lexer::token_set> 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";
+
+    // iterator type used to expose the underlying input stream
+    typedef std::string::const_iterator base_iterator_type;
+    
+    // This is the lexer token type to use. The second template parameter lists 
+    // all attribute types used for token_def's during token definition (see 
+    // calculator_tokens<> above). Here we use the predefined lexertl token 
+    // type, but any compatible token type may be used.
+    typedef lexertl_token<
+        base_iterator_type, boost::mpl::vector<unsigned int> 
+    > token_type;
+    
+    // This is the lexer type to use to tokenize the input.
+    // Here we use the lexertl based lexer engine.
+    typedef lexertl_lexer<base_iterator_type, token_type> lexer_type;
+    
+    // This is the token definition type (derived from the given lexer type).
+    typedef calculator_tokens<lexer_type> calculator_tokens;
+    
+    // this is the iterator type exposed by the lexer 
+    typedef lexer<calculator_tokens>::iterator_type iterator_type;
+
+    // this is the type of the grammar to parse
+    typedef calculator<iterator_type, lexer_type> calculator;
+
+    // now we use the types defined above to create the lexer and grammar
+    // object instances needed to invoke the parsing process
+    calculator_tokens tokens;                       // Our token definition
+    calculator def (tokens);                        // Our grammar definition
+
+    lexer<calculator_tokens> lex(tokens);           // Our lexer
+    grammar<calculator> calc(def, def.expression);  // Our grammar
+
+    // get input line by line and feed the parser to evaluate the expressions
+    // read in from the input
+    std::string str;
+    int result;
+    while (std::getline(std::cin, str))
+    {
+        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+            break;
+
+        // At this point we generate the iterator pair used to expose the
+        // tokenized input stream.
+        iterator_type iter = lex.begin(str.begin(), str.end());
+        iterator_type end = lex.end();
+        
+        // Parsing is done based on the the token stream, not the character 
+        // stream read from the input.
+        // Note, how we use the token_set defined above as the skip parser.
+        bool r = phrase_parse(iter, end, calc, result, tokens.skipper);
+
+        if (r && iter == end)
+        {
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing succeeded\n";
+            std::cout << "result = " << result << std::endl;
+            std::cout << "-------------------------\n";
+        }
+        else
+        {
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing failed\n";
+            std::cout << "-------------------------\n";
+        }
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+
Added: trunk/libs/spirit/example/qi/calc4.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc4.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,126 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  This time, we'll incorporate error handling and reporting.
+//
+//  [ JDG June 29, 2002 ]   spirit1
+//  [ JDG March 5, 2007 ]   spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+
+#include <iostream>
+#include <string>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::val;
+using boost::phoenix::construct;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our calculator grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator : grammar_def<Iterator, int(), space_type>
+{
+    calculator()
+    {
+        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])
+            ;
+
+        expression.name("expression");
+        term.name("term");
+        factor.name("factor");
+
+        on_error<fail>
+        (   
+            expression
+          , std::cout
+                << val("Error! Expecting ")
+                << _4                               // what failed?
+                << val(" here: \"")
+                << construct<std::string>(_3, _2)   // iterators to error-pos, end
+                << val("\"")
+                << std::endl
+        );
+    }
+
+    rule<Iterator, int(), 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 calculator<iterator_type> calculator;
+
+    calculator def; //  Our grammar definition
+    grammar<calculator> calc(def, def.expression); // 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, result, space);
+
+        if (r && iter == end)
+        {
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing succeeded\n";
+            std::cout << "result = " << result << std::endl;
+            std::cout << "-------------------------\n";
+        }
+        else
+        {
+            std::cout << "-------------------------\n";
+            std::cout << "Parsing failed\n";
+            std::cout << "-------------------------\n";
+        }
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+
Added: trunk/libs/spirit/example/qi/calc5.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc5.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,227 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_container.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::ref;
+using boost::phoenix::push_back;
+using boost::phoenix::val;
+using boost::phoenix::construct;
+
+///////////////////////////////////////////////////////////////////////////////
+//  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>& code);
+
+private:
+
+    std::vector<int> stack;
+    std::vector<int>::iterator stack_ptr;
+};
+
+void vmachine::execute(std::vector<int>& code)
+{
+    std::vector<int>::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;
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our calculator grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator : grammar_def<Iterator, space_type>
+{
+    calculator(std::vector<int>& code)
+      : code(code)
+    {
+        expression =
+            term
+            >> *(   ('+' > term             [push_back(ref(code), op_add)])
+                |   ('-' > term             [push_back(ref(code), op_sub)])
+                )
+            ;
+
+        term =
+            factor
+            >> *(   ('*' > factor           [push_back(ref(code), op_mul)])
+                |   ('/' > factor           [push_back(ref(code), op_div)])
+                )
+            ;
+
+        factor =
+            uint_                           [
+                                                push_back(ref(code), op_int),
+                                                push_back(ref(code), _1)
+                                            ]
+            |   '(' > expression > ')'
+            |   ('-' > factor               [push_back(ref(code), op_neg)])
+            |   ('+' > factor)
+            ;
+
+        expression.name("expression");
+        term.name("term");
+        factor.name("factor");
+
+        on_error<fail>
+        (
+            expression
+          , std::cout
+                << val("Error! Expecting ")
+                << _4                               // what failed?
+                << val(" here: \"")
+                << construct<std::string>(_3, _2)   // iterators to error-pos, end
+                << val("\"")
+                << std::endl
+        );
+    }
+
+    rule<Iterator, space_type> expression, term, factor;
+    std::vector<int>& code;
+};
+
+template <typename Grammar>
+bool compile(Grammar const& calc, std::string const& expr)
+{
+    std::string::const_iterator iter = expr.begin();
+    std::string::const_iterator end = expr.end();
+    bool r = phrase_parse(iter, end, calc, space);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+        return true;
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+        return false;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  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 calculator<iterator_type> calculator;
+
+    vmachine mach;                  //  Our virtual machine
+    std::vector<int> code;          //  Our VM code
+    calculator def(code);           //  Our grammar definition
+    grammar<calculator>
+        calc(def, def.expression);  //  Our grammar
+
+    std::string str;
+    while (std::getline(std::cin, str))
+    {
+        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+            break;
+
+        code.clear();
+        if (::compile(calc, str))
+        {
+            mach.execute(code);
+            std::cout << "\n\nresult = " << mach.top() << std::endl;
+            std::cout << "-------------------------\n\n";
+        }
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+
Added: trunk/libs/spirit/example/qi/calc6/calc6.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc6/calc6.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,102 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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
+//
+///////////////////////////////////////////////////////////////////////////////
+#include "calc6.hpp"
+
+template <typename Grammar>
+bool compile(Grammar const& calc, std::string const& expr)
+{
+    std::string::const_iterator iter = expr.begin();
+    std::string::const_iterator end = expr.end();
+    bool r = phrase_parse(iter, end, calc, space);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+        return true;
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+        return false;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Main program
+///////////////////////////////////////////////////////////////////////////////
+struct var_printer
+{
+    var_printer(std::vector<int> const& stack)
+      : stack(stack)
+    {
+    }
+
+    template <typename String, typename Data>
+    void operator()(String const& s, Data const& data)
+    {
+        std::cout << "    " << s << ": " << stack[data] << std::endl;
+    }
+
+    std::vector<int> const& stack;
+};
+
+int
+main()
+{
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Expression parser...\n\n";
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Type some statements... ";
+    std::cout << "Then type period ('.') to compile, run and print results\n\n";
+
+    typedef std::string::const_iterator iterator_type;
+    typedef statement<iterator_type> statement;
+
+    vmachine mach;                  //  Our virtual machine
+    std::vector<int> code;          //  Our VM code
+    statement def(code);            //  Our grammar definition
+    grammar<statement> calc(def);   //  Our grammar
+
+    std::string str;
+    std::string program;
+    while (std::getline(std::cin, str))
+    {
+        if (str.empty() || str[0] == '.')
+            break;
+        program += str;
+    }
+
+    if (::compile(calc, program))
+    {
+        mach.execute(code, def.nvars);
+
+        std::cout << "Results------------------\n\n";
+        def.vars.for_each(var_printer(mach.get_stack()));
+        std::cout << "-------------------------\n\n";
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+
Added: trunk/libs/spirit/example/qi/calc6/calc6.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc6/calc6.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,183 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC6)
+#define BOOST_SPIRIT_CALC6
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_container.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::function;
+using boost::phoenix::ref;
+
+///////////////////////////////////////////////////////////////////////////////
+//  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
+};
+
+class vmachine
+{
+public:
+
+    vmachine(unsigned stackSize = 4096)
+      : stack(stackSize)
+      , stack_ptr(stack.begin())
+    {
+    }
+
+    std::vector<int> const& get_stack() const { return stack; };
+    void execute(std::vector<int>& code, int nvars);
+
+private:
+
+    std::vector<int> stack;
+    std::vector<int>::iterator stack_ptr;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  A generic compiler that compiles 1 to 3 codes
+///////////////////////////////////////////////////////////////////////////////
+struct compile_op
+{
+    template <typename A, typename B = unused_type, typename C = unused_type>
+    struct result { typedef void type; };
+
+    compile_op(std::vector<int>& code)
+      : code(code)
+    {
+    }
+
+    void operator()(int a) const
+    {
+        code.push_back(a);
+    }
+
+    void operator()(int a, int b) const
+    {
+        code.push_back(a);
+        code.push_back(b);
+    }
+
+    void operator()(int a, int b, int c) const
+    {
+        code.push_back(a);
+        code.push_back(b);
+        code.push_back(c);
+    }
+
+    std::vector<int>& code;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our error handler
+///////////////////////////////////////////////////////////////////////////////
+struct error_handler_
+{
+    template <typename, typename, typename>
+    struct result { typedef void type; };
+
+    template <typename Iterator>
+    void operator()(
+        std::string 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 expression grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct expression : grammar_def<Iterator, space_type>
+{
+    expression(std::vector<int>& code, symbols<char, int>& vars);
+
+    rule<Iterator, space_type>
+        expr, additive_expr, multiplicative_expr
+      , unary_expr, primary_expr, variable;
+
+    std::vector<int>& code;
+    symbols<char, int>& vars;
+    function<compile_op> op;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our statement grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+struct var_adder
+{
+    template <typename, typename>
+    struct result { typedef void type; };
+
+    var_adder(symbols<char, int>& vars)
+      : vars(vars)
+    {
+    }
+
+    void operator()(std::string const& var, int& nvars) const
+    {
+        vars.add(var.begin(), var.end(), nvars++);
+    };
+
+    symbols<char, int>& vars;
+};
+
+template <typename Iterator>
+struct statement : grammar_def<Iterator, space_type>
+{
+    statement(std::vector<int>& code);
+
+    std::vector<int>& code;
+    symbols<char, int> vars;
+    int nvars;
+
+    expression<Iterator> expr_def;
+    grammar<expression<Iterator> > expr;
+    rule<Iterator, space_type> start, var_decl;
+    rule<Iterator, std::string(), space_type> identifier;
+    rule<Iterator, int(), space_type> var_ref;
+    rule<Iterator, locals<int>, space_type> assignment;
+    rule<Iterator, void(int), space_type> assignment_rhs;
+
+    function<var_adder> add_var;
+    function<compile_op> op;
+};
+
+#endif
+
Added: trunk/libs/spirit/example/qi/calc6/calc6a.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc6/calc6a.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,58 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "calc6.hpp"
+
+void vmachine::execute(std::vector<int>& code, int nvars)
+{
+    std::vector<int>::iterator pc = code.begin();
+    std::vector<int>::iterator locals = stack.begin();
+    stack_ptr = stack.begin() + nvars;
+
+    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;
+        }
+    }
+}
+
Added: trunk/libs/spirit/example/qi/calc6/calc6b.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc6/calc6b.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,18 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "calc6b.hpp"
+
+// This is not really called. Its only purpose is to
+// instantiate the constructor of the grammar.
+void instantiate_expression()
+{
+    typedef std::string::const_iterator iterator_type;
+    symbols<char, int> vars;
+    std::vector<int> code;
+    expression<iterator_type> g(code, vars);
+}
+
Added: trunk/libs/spirit/example/qi/calc6/calc6b.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc6/calc6b.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,70 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC6B)
+#define BOOST_SPIRIT_CALC6B
+
+#include "calc6.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our expression grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+expression<Iterator>::expression(std::vector<int>& code, symbols<char, int>& vars)
+  : code(code)
+  , vars(vars)
+  , op(code)
+{
+    expr =
+        additive_expr.alias()
+        ;
+
+    additive_expr =
+        multiplicative_expr
+        >> *(   ('+' > multiplicative_expr  [op(op_add)])
+            |   ('-' > multiplicative_expr  [op(op_sub)])
+            )
+        ;
+
+    multiplicative_expr =
+        unary_expr
+        >> *(   ('*' > unary_expr           [op(op_mul)])
+            |   ('/' > unary_expr           [op(op_div)])
+            )
+        ;
+
+    unary_expr =
+            primary_expr
+        |   ('-' > primary_expr             [op(op_neg)])
+        |   ('+' > primary_expr)
+        ;
+
+    primary_expr =
+        uint_                               [op(op_int, _1)]
+        |   variable
+        |   '(' > expr > ')'
+        ;
+
+    variable =
+        (
+            lexeme[
+                vars
+                >> !(alnum | '_')           // make sure we have whole words
+            ]
+        )                                   [op(op_load, _1)]
+        ;
+
+    expr.name("expression");
+    additive_expr.name("additive-expression");
+    multiplicative_expr.name("multiplicative-expression");
+    unary_expr.name("unary-expression");
+    primary_expr.name("primary-expression");
+    variable.name("variable");
+
+    on_error<fail>(expr, error_handler(_4, _3, _2));
+}
+
+#endif
Added: trunk/libs/spirit/example/qi/calc6/calc6c.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc6/calc6c.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,16 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "calc6c.hpp"
+
+// This is not really called. Its only purpose is to
+// instantiate the constructor of the grammar.
+void instantiate_statement()
+{
+    typedef std::string::const_iterator iterator_type;
+    std::vector<int> code;
+    statement<iterator_type> g(code);
+}
Added: trunk/libs/spirit/example/qi/calc6/calc6c.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc6/calc6c.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,65 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC6C)
+#define BOOST_SPIRIT_CALC6C
+
+#include "calc6.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our statement grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+statement<Iterator>::statement(std::vector<int>& code)
+  : code(code)
+  , nvars(0)
+  , expr_def(code, vars)
+  , expr(expr_def, expr_def.expr)
+  , add_var(vars)
+  , op(code)
+{
+    identifier %=
+        raw[lexeme[alpha >> *(alnum | '_')]]
+        ;
+
+    var_ref =
+        lexeme
+        [
+                vars        [_val = _1]
+            >>  !(alnum | '_') // make sure we have whole words
+        ]
+        ;
+
+    var_decl =
+            "var"
+        >   !var_ref        // make sure the variable isn't redeclared
+        >   identifier      [add_var(_1, ref(nvars))]
+        >   (';' | '=' > assignment_rhs(ref(nvars)-1))
+        ;
+
+    assignment =
+            var_ref         [_a = _1]
+        >>  '='
+        >   assignment_rhs(_a)
+        ;
+
+    assignment_rhs =
+            expr
+        >   char_(';')      [op(op_store, _r1)]
+        ;
+
+    start = +(var_decl | assignment);
+
+    identifier.name("identifier");
+    var_ref.name("variable-reference");
+    var_decl.name("variable-declaration");
+    assignment.name("assignment");
+    assignment_rhs.name("assignment-rhs");
+
+    on_error<fail>(start, error_handler(_4, _3, _2));
+}
+
+#endif
\ No newline at end of file
Added: trunk/libs/spirit/example/qi/calc7/calc7.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc7/calc7.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,99 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  Now we'll introduce boolean expressions and control structures.
+//  Is it obvious now what we are up to? ;-)
+//
+//  [ JDG April 9, 2007 ]       spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#include "calc7.hpp"
+
+template <typename Grammar>
+bool compile(Grammar const& calc, std::string const& expr)
+{
+    std::string::const_iterator iter = expr.begin();
+    std::string::const_iterator end = expr.end();
+    bool r = phrase_parse(iter, end, calc, space);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+        return true;
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+        return false;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  Main program
+///////////////////////////////////////////////////////////////////////////////
+struct var_printer
+{
+    var_printer(std::vector<int> const& stack)
+      : stack(stack)
+    {
+    }
+
+    template <typename String, typename Data>
+    void operator()(String const& s, Data const& data)
+    {
+        std::cout << "    " << s << ": " << stack[data] << std::endl;
+    }
+
+    std::vector<int> const& stack;
+};
+
+int
+main()
+{
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Expression parser...\n\n";
+    std::cout << "/////////////////////////////////////////////////////////\n\n";
+    std::cout << "Type some statements... ";
+    std::cout << "Then type period ('.') to compile, run and print results\n\n";
+
+    typedef std::string::const_iterator iterator_type;
+    typedef statement<iterator_type> statement;
+
+    vmachine mach;                      //  Our virtual machine
+    std::vector<int> code;              //  Our VM code
+    statement def(code);                //  Our grammar definition
+    grammar<statement>
+        calc(def, def.statement_list);  //  Our grammar
+
+    std::string str;
+    std::string program;
+    while (std::getline(std::cin, str))
+    {
+        if (str.empty() || str[0] == '.')
+            break;
+        program += str;
+    }
+
+    if (::compile(calc, program))
+    {
+        mach.execute(code, def.nvars);
+
+        std::cout << "Results------------------\n\n";
+        def.vars.for_each(var_printer(mach.get_stack()));
+        std::cout << "-------------------------\n\n";
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+
Added: trunk/libs/spirit/example/qi/calc7/calc7.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc7/calc7.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,208 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7)
+#define BOOST_SPIRIT_CALC7
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_container.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::function;
+using boost::phoenix::ref;
+using boost::phoenix::size;
+
+///////////////////////////////////////////////////////////////////////////////
+//  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 an absolute position in the code if top stack
+                    //  evaluates to false
+    op_jump         //  jump to an absolute position in the code
+};
+
+class vmachine
+{
+public:
+
+    vmachine(unsigned stackSize = 4096)
+      : stack(stackSize)
+      , stack_ptr(stack.begin())
+    {
+    }
+
+    std::vector<int> const& get_stack() const { return stack; };
+    void execute(std::vector<int>& code, int nvars);
+
+private:
+
+    std::vector<int> stack;
+    std::vector<int>::iterator stack_ptr;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  A generic compiler that compiles 1 to 3 codes
+///////////////////////////////////////////////////////////////////////////////
+struct compile_op
+{
+    template <typename A, typename B = unused_type, typename C = unused_type>
+    struct result { typedef void type; };
+
+    compile_op(std::vector<int>& code)
+      : code(code)
+    {
+    }
+
+    void operator()(int a) const
+    {
+        code.push_back(a);
+    }
+
+    void operator()(int a, int b) const
+    {
+        code.push_back(a);
+        code.push_back(b);
+    }
+
+    void operator()(int a, int b, int c) const
+    {
+        code.push_back(a);
+        code.push_back(b);
+        code.push_back(c);
+    }
+
+    std::vector<int>& code;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our error handler
+///////////////////////////////////////////////////////////////////////////////
+struct error_handler_
+{
+    template <typename, typename, typename>
+    struct result { typedef void type; };
+
+    template <typename Iterator>
+    void operator()(
+        std::string 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 expression grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct expression : grammar_def<Iterator, space_type>
+{
+    expression(std::vector<int>& code, symbols<char, int>& vars);
+
+    rule<Iterator, space_type>
+        expr, equality_expr, relational_expr
+      , logical_expr, additive_expr, multiplicative_expr
+      , unary_expr, primary_expr, variable
+    ;
+
+    std::vector<int>& code;
+    symbols<char, int>& vars;
+    function<compile_op> op;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our statement grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+struct var_adder
+{
+    template <typename, typename>
+    struct result { typedef void type; };
+
+    var_adder(symbols<char, int>& vars)
+      : vars(vars)
+    {
+    }
+
+    void operator()(std::string const& var, int& nvars) const
+    {
+        vars.add(var.begin(), var.end(), nvars++);
+    };
+
+    symbols<char, int>& vars;
+};
+
+template <typename Iterator>
+struct statement : grammar_def<Iterator, space_type>
+{
+    statement(std::vector<int>& code);
+
+    std::vector<int>& code;
+    symbols<char, int> vars;
+    int nvars;
+
+    expression<Iterator> expr_def;
+    grammar<expression<Iterator> > expr;
+    rule<Iterator, space_type>
+        statement_, statement_list, var_decl, compound_statement
+    ;
+
+    rule<Iterator, locals<int>, space_type> if_statement;
+    rule<Iterator, locals<int, int>, space_type> while_statement;
+    rule<Iterator, std::string(), space_type> identifier;
+    rule<Iterator, int(), space_type> var_ref;
+    rule<Iterator, locals<int>, space_type> assignment;
+    rule<Iterator, void(int), space_type> assignment_rhs;
+
+    function<var_adder> add_var;
+    function<compile_op> op;
+};
+
+#endif
Added: trunk/libs/spirit/example/qi/calc7/calc7a.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc7/calc7a.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,125 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "calc7.hpp"
+
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+                                // (performance warning)
+
+void vmachine::execute(std::vector<int>& code, int nvars)
+{
+    std::vector<int>::iterator pc = code.begin();
+    std::vector<int>::iterator locals = stack.begin();
+    stack_ptr = stack.begin() + nvars;
+
+    while (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++ = locals[*pc++];
+                break;
+
+            case op_store:
+                --stack_ptr;
+                locals[*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 = code.begin() + *pc;
+                break;
+
+            case op_jump_if:
+                if (!bool(stack_ptr[-1]))
+                    pc = code.begin() + *pc;
+                else
+                    ++pc;
+                --stack_ptr;
+                break;
+        }
+    }
+}
+
Added: trunk/libs/spirit/example/qi/calc7/calc7b.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc7/calc7b.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,17 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "calc7b.hpp"
+
+// This is not really called. Its only purpose is to
+// instantiate the constructor of the grammar.
+void instantiate_expression()
+{
+    typedef std::string::const_iterator iterator_type;
+    symbols<char, int> vars;
+    std::vector<int> code;
+    expression<iterator_type> g(code, vars);
+}
Added: trunk/libs/spirit/example/qi/calc7/calc7b.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc7/calc7b.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,101 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7B)
+#define BOOST_SPIRIT_CALC7B
+
+#include "calc7.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our expression grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+expression<Iterator>::expression(std::vector<int>& code, symbols<char, int>& vars)
+  : code(code)
+  , vars(vars)
+  , op(code)
+{
+    expr =
+        equality_expr.alias()
+        ;
+
+    equality_expr =
+        relational_expr
+        >> *(   ("==" > relational_expr     [op(op_eq)])
+            |   ("!=" > relational_expr     [op(op_neq)])
+            )
+        ;
+
+    relational_expr =
+        logical_expr
+        >> *(   ("<=" > logical_expr        [op(op_lte)])
+            |   ('<' > logical_expr         [op(op_lt)])
+            |   (">=" > logical_expr        [op(op_gte)])
+            |   ('>' > logical_expr         [op(op_gt)])
+            )
+        ;
+
+    logical_expr =
+        additive_expr
+        >> *(   ("&&" > additive_expr       [op(op_and)])
+            |   ("||" > additive_expr       [op(op_or)])
+            )
+        ;
+
+    additive_expr =
+        multiplicative_expr
+        >> *(   ('+' > multiplicative_expr  [op(op_add)])
+            |   ('-' > multiplicative_expr  [op(op_sub)])
+            )
+        ;
+
+    multiplicative_expr =
+        unary_expr
+        >> *(   ('*' > unary_expr           [op(op_mul)])
+            |   ('/' > unary_expr           [op(op_div)])
+            )
+        ;
+
+    unary_expr =
+            primary_expr
+        |   ('!' > primary_expr             [op(op_not)])
+        |   ('-' > primary_expr             [op(op_neg)])
+        |   ('+' > primary_expr)
+        ;
+
+    primary_expr =
+        uint_                               [op(op_int, _1)]
+        |   variable
+        |   lit("true")                     [op(op_true)]
+        |   lit("false")                    [op(op_false)]
+        |   '(' > expr > ')'
+        ;
+
+    variable =
+        (
+            lexeme[
+                vars
+                >> !(alnum | '_')           // make sure we have whole words
+            ]
+        )                                   [op(op_load, _1)]
+        ;
+
+    expr.name("expression");
+    equality_expr.name("equality-expression");
+    relational_expr.name("relational-expression");
+    logical_expr.name("logical-expression");
+    additive_expr.name("additive-expression");
+    multiplicative_expr.name("multiplicative-expression");
+    unary_expr.name("unary-expression");
+    primary_expr.name("primary-expression");
+    variable.name("variable");
+
+    on_error<fail>(expr, error_handler(_4, _3, _2));
+}
+
+#endif
+
+
Added: trunk/libs/spirit/example/qi/calc7/calc7c.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc7/calc7c.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,16 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "calc7c.hpp"
+
+// This is not really called. Its only purpose is to
+// instantiate the constructor of the grammar.
+void instantiate_statement()
+{
+    typedef std::string::const_iterator iterator_type;
+    std::vector<int> code;
+    statement<iterator_type> g(code);
+}
Added: trunk/libs/spirit/example/qi/calc7/calc7c.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/calc7/calc7c.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,131 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7C)
+#define BOOST_SPIRIT_CALC7C
+
+#include "calc7.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our statement grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+statement<Iterator>::statement(std::vector<int>& code)
+  : code(code)
+  , nvars(0)
+  , expr_def(code, vars)
+  , expr(expr_def, expr_def.expr)
+  , add_var(vars)
+  , op(code)
+{
+    identifier %=
+        raw[lexeme[alpha >> *(alnum | '_')]]
+        ;
+
+    var_ref =
+        lexeme
+        [
+                vars        [_val = _1]
+            >>  !(alnum | '_') // make sure we have whole words
+        ]
+        ;
+
+    var_decl =
+            "var"
+        >   !var_ref        // make sure the variable isn't redeclared
+        >   identifier      [add_var(_1, ref(nvars))]
+        >   (';' | '=' > assignment_rhs(ref(nvars)-1))
+        ;
+
+    assignment =
+            var_ref         [_a = _1]
+        >>  '='
+        >   assignment_rhs(_a)
+        ;
+
+    assignment_rhs =
+            expr
+        >   char_(';')       [op(op_store, _r1)]
+        ;
+
+    if_statement =
+            lit("if")
+        >>  '('
+        >   expr            [
+                                op(op_jump_if, 0), // we shall fill this (0) in later
+                                _a = size(ref(code))-1 // mark its position
+                            ]
+        >   ')'
+        >   statement_      [
+                                // now we know where to jump to (after the if branch)
+                                ref(code)[_a] = size(ref(code))
+                            ]
+        >>
+           -(
+                lexeme[
+                    "else"
+                    >> !(alnum | '_') // make sure we have whole words
+                ]
+                            [
+                                ref(code)[_a] += 2, // adjust for the "else" jump
+                                op(op_jump, 0), // we shall fill this (0) in later
+                                _a = size(ref(code))-1 // mark its position
+                            ]
+            >   statement_  [
+                                // now we know where to jump to (after the else branch)
+                                ref(code)[_a] = size(ref(code))
+                            ]
+            )
+        ;
+
+    while_statement =
+            lit("while")    [
+                                _a = size(ref(code)) // mark our position
+                            ]
+        >>  '('
+        >   expr            [
+                                op(op_jump_if, 0), // we shall fill this (0) in later
+                                _b = size(ref(code))-1 // mark its position
+                            ]
+        >   ')'
+        >   statement_      [
+                                op(op_jump, _a), // loop back
+                                // now we know where to jump to (to exit the loop)
+                                ref(code)[_b] = size(ref(code))
+                            ]
+        ;
+
+    compound_statement =
+        '{' >> -statement_list >> '}'
+        ;
+
+    statement_ =
+            var_decl
+        |   assignment
+        |   compound_statement
+        |   if_statement
+        |   while_statement
+        ;
+
+    statement_list = +statement_;
+
+    identifier.name("identifier");
+    var_ref.name("variable-reference");
+    var_decl.name("variable-declaration");
+    assignment.name("assignment");
+    assignment_rhs.name("assignment-rhs");
+    if_statement.name("if-statement");
+    while_statement.name("while-statement");
+    compound_statement.name("compound-statement");
+    statement_.name("statement");
+    statement_list.name("statement-list");
+
+    on_error<fail>(statement_list, error_handler(_4, _3, _2));
+}
+
+#endif
+
+
Added: trunk/libs/spirit/example/qi/complex_number.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/complex_number.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,94 @@
+/*=============================================================================
+    Copyright (c) 2002-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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  A complex number micro parser.
+//
+//  [ JDG May 10, 2002 ]    spirit1
+//  [ JDG May 9, 2007 ]     spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#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>
+
+using namespace boost::phoenix;
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our complex number parser/compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+{
+    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 (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;
+}
+
+
Added: trunk/libs/spirit/example/qi/employee.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/employee.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,132 @@
+/*=============================================================================
+    Copyright (c) 2002-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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  A parser for arbitrary tuples. This example presents a parser
+//  for an employee structure.
+//
+//  [ JDG May 9, 2007 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+#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>
+
+using namespace boost::phoenix;
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our 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
+BOOST_FUSION_ADAPT_STRUCT(
+    employee,
+    (int, age)
+    (std::string, surname)
+    (std::string, forename)
+    (double, salary)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our employee parser
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct employee_parser : grammar_def<Iterator, employee(), space_type>
+{
+    employee_parser()
+    {
+        quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
+
+        start %=
+            lit("employee")
+            >> '{'
+            >>  int_ >> ','
+            >>  quoted_string >> ','
+            >>  quoted_string >> ','
+            >>  double_
+            >>  '}'
+            ;
+    }
+
+    rule<Iterator, std::string(), space_type> quoted_string;
+    rule<Iterator, employee(), 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";
+
+    typedef std::string::const_iterator iterator_type;
+    typedef employee_parser<iterator_type> employee_parser;
+
+    employee_parser def; //  Our grammar definition
+    grammar<employee_parser> g(def); // Our grammar
+    std::string str;
+    while (getline(std::cin, str))
+    {
+        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+            break;
+
+        employee emp;
+        std::string::const_iterator iter = str.begin();
+        std::string::const_iterator end = str.end();
+        bool r = phrase_parse(iter, end, g, emp, space);
+
+        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;
+}
+
+
Added: trunk/libs/spirit/example/qi/mini_c/mini_c.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_c.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,123 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  Not a calculator anymore, right? :-)
+//
+//  [ JDG April 10, 2007 ]       spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#include "mini_c.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our main compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Grammar>
+bool compile(Grammar const& prog, std::string const& expr)
+{
+    typedef white_space_def<std::string::const_iterator> white_space_def;
+    white_space_def white_;                         //  Our skipper definition
+    grammar<white_space_def> white_space(white_);   //  Our skipper
+
+    std::string::const_iterator iter = expr.begin();
+    std::string::const_iterator end = expr.end();
+    bool r = phrase_parse(iter, end, prog, white_space);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+        return true;
+    }
+    else
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing failed\n";
+        std::cout << "-------------------------\n";
+        return false;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  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;
+    typedef program<iterator_type> program;
+
+    vmachine mach;              //  Our virtual machine
+    std::vector<int> code;      //  Our VM code
+    program def(code);          //  Our grammar definition
+    grammar<program> prog(def); //  Our grammar
+
+    if (::compile(prog, source_code))
+    {
+        std::string fmain("main");
+        std::string::iterator fbegin = fmain.begin();
+        function_info* f = def.functions.lookup()->find(fbegin, fmain.end());
+        if (f == 0)
+        {
+            std::cerr << "Error: main function not defined" << std::endl;
+            return 1;
+        }
+
+        int nargs = argc-2;
+        if (f->arity != nargs)
+        {
+            std::cerr << "Error: main function requires " << f->arity << " arguments." << std::endl;
+            std::cerr << nargs << "supplied." << std::endl;
+            return 1;
+        }
+
+        for (int i = 0; i < nargs; ++i)
+            mach.stack[i] = boost::lexical_cast<int>(argv[i+2]);
+
+        int r = mach.execute(
+            code                                // code
+          , code.begin() + f->address           // pc
+          , mach.stack.begin()                  // frame_ptr
+        );
+
+        std::cout << "-------------------------\n";
+        std::cout << "Result: " << r << std::endl;
+        std::cout << "-------------------------\n\n";
+    }
+
+    std::cout << "Bye... :-) \n\n";
+    return 0;
+}
+
+
Added: trunk/libs/spirit/example/qi/mini_c/mini_c.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_c.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,354 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINI_C)
+#define BOOST_SPIRIT_MINI_C
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_container.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/lexical_cast.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+using boost::phoenix::function;
+using boost::phoenix::ref;
+using boost::phoenix::size;
+
+///////////////////////////////////////////////////////////////////////////////
+//  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 an absolute position in the code if top stack
+                    //  evaluates to false
+    op_jump,        //  jump to an absolute 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
+    );
+
+    std::vector<int> stack;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  A generic compiler that compiles 1 to 3 codes
+///////////////////////////////////////////////////////////////////////////////
+struct function_info
+{
+    int arity;
+    int address;
+};
+
+struct compile_op
+{
+    template <typename A, typename B = unused_type, typename C = unused_type>
+    struct result { typedef void type; };
+
+    compile_op(std::vector<int>& code)
+      : code(code)
+    {
+    }
+
+    void operator()(int a) const
+    {
+        code.push_back(a);
+    }
+
+    void operator()(int a, int b) const
+    {
+        code.push_back(a);
+        code.push_back(b);
+    }
+
+    void operator()(int a, int b, int c) const
+    {
+        code.push_back(a);
+        code.push_back(b);
+        code.push_back(c);
+    }
+
+    // special overload for function calls
+    void operator()(function_info const& info, int got_nargs, bool& parse_result) const
+    {
+        if (got_nargs == info.arity)
+        {
+            code.push_back(op_call);
+            code.push_back(info.arity);
+            code.push_back(info.address);
+        }
+        else
+        {
+            parse_result = false; // fail the parse
+            std::cerr << "wrong number of args" << std::endl;
+        }
+    }
+
+    std::vector<int>& code;
+};
+
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our error handler
+///////////////////////////////////////////////////////////////////////////////
+struct error_handler_
+{
+    template <typename, typename, typename>
+    struct result { typedef void type; };
+
+    template <typename Iterator>
+    void operator()(
+        std::string 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_();
+
+///////////////////////////////////////////////////////////////////////////////
+//  A functor that adds variables to our (variables) symbol-table
+///////////////////////////////////////////////////////////////////////////////
+struct var_adder
+{
+    template <typename>
+    struct result { typedef void type; };
+
+    var_adder(symbols<char, int>& vars, int& nvars)
+      : vars(vars), nvars(nvars)
+    {
+    }
+
+    void operator()(std::string const& var) const
+    {
+        vars.add(var.begin(), var.end(), nvars++);
+    };
+
+    symbols<char, int>& vars;
+    int& nvars;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  A functor that adds functions to our (function) symbol-table
+///////////////////////////////////////////////////////////////////////////////
+struct function_adder
+{
+    template <typename, typename, typename>
+    struct result { typedef void type; };
+
+    function_adder(symbols<char, function_info>& functions)
+      : functions(functions)
+    {
+    }
+
+    void operator()(std::string const& function_id, int arity, int address) const
+    {
+        function_info info = {arity, address};
+        functions.add(function_id.begin(), function_id.end(), info);
+    };
+
+    symbols<char, function_info>& functions;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  A functor that resets the function-related state variables
+///////////////////////////////////////////////////////////////////////////////
+struct function_state_reset
+{
+    template <typename>
+    struct result { typedef void type; };
+
+    function_state_reset(
+        std::vector<int>& code
+      , symbols<char, int>& vars
+      , int& nvars)
+      : code(code)
+      , vars(vars)
+      , nvars(nvars)
+    {
+    }
+
+    void operator()(int address) const
+    {
+        code[address+1] = nvars;
+        nvars = 0; // reset
+        vars.clear(); // reset
+    };
+
+    std::vector<int>& code;
+    symbols<char, int>& vars;
+    int& nvars;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  White-space and comments grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct white_space_def : grammar_def<Iterator>
+{
+    white_space_def()
+    {
+        start =
+                space                               // tab/space/cr/lf
+            |   "/*" >> *(char_ - "*/") >> "*/"     // C-style comments
+            ;
+    }
+
+    rule<Iterator> start;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our expression grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct expression : grammar_def<Iterator, grammar<white_space_def<Iterator> > >
+{
+    expression(
+        std::vector<int>& code
+      , symbols<char, int>& vars
+      , symbols<char, function_info>& functions);
+
+    typedef grammar<white_space_def<Iterator> > white_space;
+
+    rule<Iterator, white_space>
+        expr, equality_expr, relational_expr
+      , logical_expr, additive_expr, multiplicative_expr
+      , unary_expr, primary_expr, variable
+    ;
+
+    rule<Iterator, locals<function_info, int>, white_space> function_call;
+
+    std::vector<int>& code;
+    symbols<char, int>& vars;
+    symbols<char, function_info>& functions;
+    function<compile_op> op;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our statement grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct statement : grammar_def<Iterator, grammar<white_space_def<Iterator> > >
+{
+    statement(std::vector<int>& code, symbols<char, function_info>& functions);
+
+    typedef grammar<white_space_def<Iterator> > white_space;
+
+    std::vector<int>& code;
+    symbols<char, int> vars;
+    symbols<char, function_info>& functions;
+    int nvars;
+    bool has_return;
+
+    expression<Iterator> expr_def;
+    grammar<expression<Iterator> > expr;
+    rule<Iterator, white_space>
+        statement_, statement_list, var_decl, compound_statement
+      , return_statement;
+
+    rule<Iterator, locals<int>, white_space> if_statement;
+    rule<Iterator, locals<int, int>, white_space> while_statement;
+    rule<Iterator, std::string(), white_space> identifier;
+    rule<Iterator, int(), white_space> var_ref;
+    rule<Iterator, locals<int>, white_space> assignment;
+    rule<Iterator, void(int), white_space> assignment_rhs;
+
+    function<var_adder> add_var;
+    function<compile_op> op;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our program grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct program : grammar_def<Iterator, grammar<white_space_def<Iterator> > >
+{
+    program(std::vector<int>& code);
+
+    typedef grammar<white_space_def<Iterator> > white_space;
+
+    std::vector<int>& code;
+    rule<Iterator, std::string(), white_space> identifier;
+    rule<Iterator, white_space> start;
+
+    typedef
+        locals<
+            std::string // function name
+          , int         // address
+        >
+    function_locals;
+
+    symbols<char, function_info> functions;
+    statement<Iterator> statement_def;
+    grammar<statement<Iterator> > statement;
+
+    rule<Iterator, function_locals, white_space> function;
+    boost::phoenix::function<function_adder> add_function;
+    boost::phoenix::function<function_state_reset> state_reset;
+    boost::phoenix::function<compile_op> op;
+};
+
+#endif
+
+
Added: trunk/libs/spirit/example/qi/mini_c/mini_ca.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_ca.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,155 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "mini_c.hpp"
+
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+                                // (performance warning)
+
+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)
+    {
+        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 = code.begin() + *pc;
+                break;
+
+            case op_jump_if:
+                if (!bool(stack_ptr[-1]))
+                    pc = code.begin() + *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];
+        }
+    }
+}
+
Added: trunk/libs/spirit/example/qi/mini_c/mini_cb.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_cb.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,19 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "mini_cb.hpp"
+
+// This is not really called. Its only purpose is to
+// instantiate the constructor of the grammar.
+void instantiate_expression()
+{
+    typedef std::string::const_iterator iterator_type;
+    symbols<char, function_info> functions;
+    symbols<char, int> vars;
+    std::vector<int> code;
+    expression<iterator_type> g(code, vars, functions);
+}
+
Added: trunk/libs/spirit/example/qi/mini_c/mini_cb.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_cb.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,115 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINI_CB)
+#define BOOST_SPIRIT_MINI_CB
+
+#include "mini_c.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our expression grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+expression<Iterator>::expression(
+    std::vector<int>& code
+  , symbols<char, int>& vars
+  , symbols<char, function_info>& functions)
+  : code(code)
+  , vars(vars)
+  , functions(functions)
+  , op(code)
+{
+    expr =
+        equality_expr.alias()
+        ;
+
+    equality_expr =
+        relational_expr
+        >> *(   ("==" > relational_expr     [op(op_eq)])
+            |   ("!=" > relational_expr     [op(op_neq)])
+            )
+        ;
+
+    relational_expr =
+        logical_expr
+        >> *(   ("<=" > logical_expr        [op(op_lte)])
+            |   ('<' > logical_expr         [op(op_lt)])
+            |   (">=" > logical_expr        [op(op_gte)])
+            |   ('>' > logical_expr         [op(op_gt)])
+            )
+        ;
+
+    logical_expr =
+        additive_expr
+        >> *(   ("&&" > additive_expr       [op(op_and)])
+            |   ("||" > additive_expr       [op(op_or)])
+            )
+        ;
+
+    additive_expr =
+        multiplicative_expr
+        >> *(   ('+' > multiplicative_expr  [op(op_add)])
+            |   ('-' > multiplicative_expr  [op(op_sub)])
+            )
+        ;
+
+    multiplicative_expr =
+        unary_expr
+        >> *(   ('*' > unary_expr           [op(op_mul)])
+            |   ('/' > unary_expr           [op(op_div)])
+            )
+        ;
+
+    unary_expr =
+            primary_expr
+        |   ('!' > primary_expr             [op(op_not)])
+        |   ('-' > primary_expr             [op(op_neg)])
+        |   ('+' > primary_expr)
+        ;
+
+    primary_expr =
+        uint_                               [op(op_int, _1)]
+        |   variable
+        |   function_call
+        |   lit("true")                     [op(op_true)]
+        |   lit("false")                    [op(op_false)]
+        |   '(' > expr > ')'
+        ;
+
+    variable =
+        (
+            lexeme[
+                vars
+                >> !(alnum | '_')           // make sure we have whole words
+            ]
+        )                                   [op(op_load, _1)]
+        ;
+
+    function_call =
+        functions                           [_a = _1]
+        >>  '('
+        >> -(
+                expr                        [++_b]
+                >> *(',' > expr             [++_b])
+            )
+        >   char_(')')                      [op(_a, _b, pass)]
+        ;
+
+    expr.name("expression");
+    equality_expr.name("equality-expression");
+    relational_expr.name("relational-expression");
+    logical_expr.name("logical-expression");
+    additive_expr.name("additive-expression");
+    multiplicative_expr.name("multiplicative-expression");
+    unary_expr.name("unary-expression");
+    primary_expr.name("primary-expression");
+    variable.name("variable");
+    function_call.name("function-call");
+
+    on_error<fail>(expr, error_handler(_4, _3, _2));
+}
+
+#endif
Added: trunk/libs/spirit/example/qi/mini_c/mini_cc.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_cc.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,17 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "mini_cc.hpp"
+
+// This is not really called. Its only purpose is to
+// instantiate the constructor of the grammar.
+void instantiate_statement()
+{
+    typedef std::string::const_iterator iterator_type;
+    symbols<char, function_info> functions;
+    std::vector<int> code;
+    statement<iterator_type> g(code, functions);
+}
Added: trunk/libs/spirit/example/qi/mini_c/mini_cc.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_cc.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,144 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINI_CC)
+#define BOOST_SPIRIT_MINI_CC
+
+#include "mini_c.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our statement grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+statement<Iterator>::statement(
+    std::vector<int>& code, symbols<char, function_info>& functions)
+  : code(code)
+  , functions(functions)
+  , nvars(0)
+  , expr_def(code, vars, functions)
+  , expr(expr_def, expr_def.expr)
+  , add_var(var_adder(vars, nvars))
+  , op(code)
+{
+    identifier %=
+        raw[lexeme[alpha >> *(alnum | '_')]]
+        ;
+
+    var_ref =
+        lexeme
+        [
+                vars        [_val = _1]
+            >>  !(alnum | '_') // make sure we have whole words
+        ]
+        ;
+
+    var_decl =
+            "int"
+        >   !var_ref        // make sure the variable isn't redeclared
+        >   identifier      [add_var(_1)]
+        >   (';' | '=' > assignment_rhs(ref(nvars)-1))
+        ;
+
+    assignment =
+            var_ref         [_a = _1]
+        >>  '='
+        >   assignment_rhs(_a)
+        ;
+
+    assignment_rhs =
+            expr
+        >   char_(';')      [op(op_store, _r1)]
+        ;
+
+    if_statement =
+            lit("if")
+        >>  '('
+        >   expr            [
+                                op(op_jump_if, 0), // we shall fill this (0) in later
+                                _a = size(ref(code))-1 // mark its position
+                            ]
+        >   ')'
+        >   statement_      [
+                                // now we know where to jump to (after the if branch)
+                                ref(code)[_a] = size(ref(code))
+                            ]
+        >>
+           -(
+                lexeme[
+                    "else"
+                    >> !(alnum | '_') // make sure we have whole words
+                ]                                [
+                                ref(code)[_a] += 2, // adjust for the "else" jump
+                                op(op_jump, 0), // we shall fill this (0) in later
+                                _a = size(ref(code))-1 // mark its position
+                            ]
+            >   statement_  [
+                                // now we know where to jump to (after the else branch)
+                                ref(code)[_a] = size(ref(code))
+                            ]
+            )
+        ;
+
+    while_statement =
+            lit("while")    [
+                                _a = size(ref(code)) // mark our position
+                            ]
+        >>  '('
+        >   expr            [
+                                op(op_jump_if, 0), // we shall fill this (0) in later
+                                _b = size(ref(code))-1 // mark its position
+                            ]
+        >   ')'
+        >   statement_      [
+                                op(op_jump, _a), // loop back
+                                // now we know where to jump to (to exit the loop)
+                                ref(code)[_b] = size(ref(code))
+                            ]
+        ;
+
+    compound_statement =
+        '{' >> -statement_list >> '}'
+        ;
+
+    return_statement =
+            lexeme[
+                "return"
+                >> !(alnum | '_') // make sure we have whole words
+            ]
+        >> -(
+                eps(ref(has_return)) > expr     [op(op_return)]
+            )
+        >   ';'
+        ;
+
+    statement_ =
+            var_decl
+        |   assignment
+        |   compound_statement
+        |   if_statement
+        |   while_statement
+        |   return_statement
+        ;
+
+    statement_list = +statement_;
+
+    identifier.name("identifier");
+    var_ref.name("variable-reference");
+    var_decl.name("variable-declaration");
+    assignment.name("assignment");
+    assignment_rhs.name("assignment-rhs");
+    if_statement.name("if-statement");
+    while_statement.name("while-statement");
+    compound_statement.name("compound-statement");
+    return_statement.name("return-statement");
+    statement_.name("statement");
+    statement_list.name("statement-list");
+
+    on_error<fail>(statement_list, error_handler(_4, _3, _2));
+}
+
+#endif
+
Added: trunk/libs/spirit/example/qi/mini_c/mini_cd.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_cd.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,16 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include "mini_cd.hpp"
+
+// This is not really called. Its only purpose is to
+// instantiate the constructor of the grammar.
+void instantiate_program()
+{
+    typedef std::string::const_iterator iterator_type;
+    std::vector<int> code;
+    program<iterator_type> g(code);
+}
Added: trunk/libs/spirit/example/qi/mini_c/mini_cd.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_c/mini_cd.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,71 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINI_CD)
+#define BOOST_SPIRIT_MINI_CD
+
+#include "mini_c.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our program grammar and compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+program<Iterator>::program(std::vector<int>& code)
+  : code(code)
+  , statement_def(code, functions)
+  , statement(statement_def, statement_def.statement_list)
+  , add_function(function_adder(functions))
+  , state_reset(function_state_reset(code, statement_def.vars, statement_def.nvars))
+  , op(code)
+{
+    bool& has_return = statement_def.has_return;
+    int& nvars = statement_def.nvars;
+    boost::phoenix::function<var_adder>& add_var = statement_def.add_var;
+
+    identifier %=
+        raw[lexeme[alpha >> *(alnum | '_')]]
+        ;
+
+    function =
+            (
+                lit("void")                     [ref(has_return) = false]
+            |   lit("int")                      [ref(has_return) = true]
+            )
+        >>  !functions                          // no duplicate functions!
+        >>  identifier                          [_a = _1]
+        >>  '('
+        >  -(
+                identifier                      [add_var(_1)]
+                >> *(',' > identifier           [add_var(_1)])
+            )
+        >   ')'
+        >   char_('{')                          [
+                                                    _b = size(ref(code)),
+                                                    add_function(
+                                                        _a     // function name
+                                                      , ref(nvars)      // arity
+                                                      , size(ref(code)) // address
+                                                    ),
+                                                    op(op_stk_adj, 0)   // adjust this later
+                                                ]
+        >   statement
+        >   char_('}')                          [state_reset(_b)]
+        ;
+
+    start =
+        +function
+        ;
+
+    identifier.name("identifier");
+    function.name("function");
+    start.name("program");
+
+    on_error<fail>(start, error_handler(_4, _3, _2));
+}
+
+#endif
+
+
Added: trunk/libs/spirit/example/qi/mini_xml1.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_xml1.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,224 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  A mini XML-like parser
+//
+//  [ JDG March 25, 2007 ]   spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#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>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+namespace fusion = boost::fusion;
+namespace phoenix = boost::phoenix;
+
+using phoenix::at_c;
+using phoenix::push_back;
+
+///////////////////////////////////////////////////////////////////////////////
+//  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(
+    mini_xml,
+    (std::string, name)
+    (std::vector<mini_xml_node>, children)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+//  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
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct mini_xml_def : grammar_def<Iterator, mini_xml(), space_type>
+{
+    mini_xml_def()
+    {
+        text = lexeme[+(char_ - '<')        [_val += _1]];
+        node = (xml | text)                 [_val = _1];
+
+        start_tag =
+                '<'
+            >>  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))
+        ;
+    }
+
+    rule<Iterator, mini_xml(), space_type> xml;
+    rule<Iterator, mini_xml_node(), space_type> node;
+    rule<Iterator, std::string(), space_type> text;
+    rule<Iterator, std::string(), space_type> start_tag;
+    rule<Iterator, void(std::string), 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 mini_xml_def<std::string::const_iterator> mini_xml_def;
+    mini_xml_def def;  //  Our grammar definition
+    grammar<mini_xml_def> xml(def, def.xml); // Our grammar
+    mini_xml ast; // our tree
+
+    std::string::const_iterator iter = storage.begin();
+    std::string::const_iterator end = storage.end();
+    bool r = phrase_parse(iter, end, xml, ast, space);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+        mini_xml_printer printer;
+        printer(ast);
+        return 0;
+    }
+    else
+    {
+        std::string::const_iterator some = iter+30;
+        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;
+    }
+}
+
+
Added: trunk/libs/spirit/example/qi/mini_xml2.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_xml2.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,225 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  A mini XML-like parser
+//
+//  [ JDG March 25, 2007 ]   spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#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>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+namespace fusion = boost::fusion;
+namespace phoenix = boost::phoenix;
+
+using phoenix::at_c;
+using phoenix::push_back;
+
+///////////////////////////////////////////////////////////////////////////////
+//  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(
+    mini_xml,
+    (std::string, name)
+    (std::vector<mini_xml_node>, children)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+//  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
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct mini_xml_def
+  : grammar_def<Iterator, mini_xml(), locals<std::string>, space_type>
+{
+    mini_xml_def()
+    {
+        text %= lexeme[+(char_ - '<')];
+        node %= xml | text;
+
+        start_tag %=
+                '<'
+            >>  lexeme[+(char_ - '>')]
+            >>  '>'
+        ;
+
+        end_tag =
+                "</"
+            >>  lit(_r1)
+            >>  '>'
+        ;
+
+        xml %=
+                start_tag[_a = _1]
+            >>  *node
+            >>  end_tag(_a)
+        ;
+    }
+
+    rule<Iterator, mini_xml(), locals<std::string>, space_type> xml;
+    rule<Iterator, mini_xml_node(), space_type> node;
+    rule<Iterator, std::string(), space_type> text;
+    rule<Iterator, std::string(), space_type> start_tag;
+    rule<Iterator, void(std::string), 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 mini_xml_def<std::string::const_iterator> mini_xml_def;
+    mini_xml_def def;  //  Our grammar definition
+    grammar<mini_xml_def> xml(def, def.xml); // Our grammar
+    mini_xml ast; // our tree
+
+    std::string::const_iterator iter = storage.begin();
+    std::string::const_iterator end = storage.end();
+    bool r = phrase_parse(iter, end, xml, ast, space);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+        mini_xml_printer printer;
+        printer(ast);
+        return 0;
+    }
+    else
+    {
+        std::string::const_iterator some = iter+30;
+        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;
+    }
+}
+
+
Added: trunk/libs/spirit/example/qi/mini_xml_karma.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_xml_karma.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,262 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2007 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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  A mini XML-like parser, Karma is used to print out the generated AST
+//
+//  [ JDG March 25, 2007 ]   spirit2
+//  [ HK April 02, 2007  ]   spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.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/function_output_iterator.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::karma;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+namespace fusion = boost::fusion;
+namespace phoenix = boost::phoenix;
+
+using phoenix::at_c;
+using phoenix::push_back;
+
+///////////////////////////////////////////////////////////////////////////////
+//  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(
+    mini_xml,
+    (std::string, name)
+    (std::vector<mini_xml_node>, children)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our mini XML grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct mini_xml_parser :
+    qi::grammar_def<Iterator, mini_xml(), space_type>
+{
+    mini_xml_parser()
+    {
+        text = lexeme[+(char_ - '<')        [text.val += _1]];
+        node = (xml | text)                 [node.val = _1];
+
+        start_tag =
+                '<'
+            >>  lexeme[+(char_ - '>')       [start_tag.val += _1]]
+            >>  '>'
+        ;
+
+        end_tag =
+                "</"
+            >>  lit(end_tag._1)
+            >>  '>'
+        ;
+
+        xml =
+                start_tag                   [at_c<0>(xml.val) = _1]
+            >>  *node                       [push_back(at_c<1>(xml.val), _1)]
+            >>  end_tag(at_c<0>(xml.val))
+        ;
+    }
+
+    qi::rule<Iterator, mini_xml(), space_type> xml;
+    qi::rule<Iterator, mini_xml_node(), space_type> node;
+    qi::rule<Iterator, std::string(), space_type> text;
+    qi::rule<Iterator, std::string(), space_type> start_tag;
+    qi::rule<Iterator, void(std::string), space_type> end_tag;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+///////////////////////////////////////////////////////////////////////////////
+template <typename String>
+struct string_appender
+{
+    string_appender(String& s)
+    :   str(s)
+    {}
+
+    template <typename T>
+    void operator()(T const &x) const
+    {
+        str += x;
+    }
+
+    String& str;
+};
+
+template <typename String>
+inline string_appender<String>
+make_string_appender(String& str)
+{
+    return string_appender<String>(str);
+}
+
+template <typename Char>
+struct output_iterator
+{
+    typedef std::basic_string<Char> string_type;
+    typedef string_appender<string_type> appender_type;
+    typedef boost::function_output_iterator<appender_type> type;
+    
+    static type 
+    call(std::basic_string<Char>& str)
+    {
+        return boost::make_function_output_iterator(
+            make_string_appender(str));
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+///////////////////////////////////////////////////////////////////////////////
+template <typename OutputIterator>
+struct mini_xml_generator
+  : boost::spirit::karma::grammar_def<OutputIterator, void(mini_xml), space_type>
+{
+// typedef karma::grammar_def<OutputIterator, void(mini_xml), space_type> base_type;
+// boost::mpl::print<typename base_type::start_type::param_types> x;
+
+    mini_xml_generator()
+    {
+//             text = verbatim[lit(text._1)];
+//             node = (xml | text)                 [_1 = node._1];
+//
+//             start_tag =
+//                     '<'
+//                 <<  verbatim[lit(start_tag._1)]
+//                 <<  '>'
+//             ;
+//
+//             end_tag =
+//                     "</"
+//                 <<  verbatim[lit(end_tag._1)]
+//                 <<  '>'
+//             ;
+//
+//         xml =
+//                 start_tag(at_c<0>(xml._1))
+//                 <<  (*node)                     [ref(at_c<1>(xml._1))]
+//             <<  end_tag(at_c<0>(xml._1))
+        ;
+    }
+
+    karma::rule<OutputIterator, void(mini_xml), space_type> xml;
+//     karma::rule<OutputIterator, void(mini_xml_node), space_type> node;
+//     karma::rule<OutputIterator, void(std::string), space_type> text;
+//     karma::rule<OutputIterator, void(std::string), space_type> start_tag;
+//     karma::rule<OutputIterator, void(std::string), 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 mini_xml_parser<std::string::const_iterator> mini_xml_parser;
+    mini_xml_parser def;  //  Our grammar definition
+    qi::grammar<mini_xml_parser> xmlin(def, def.xml); // Our grammar
+    mini_xml ast; // our tree
+
+    std::string::const_iterator iter = storage.begin();
+    std::string::const_iterator end = storage.end();
+    bool r = phrase_parse(iter, end, xmlin, ast, space);
+
+    if (r && iter == end)
+    {
+        std::cout << "-------------------------\n";
+        std::cout << "Parsing succeeded\n";
+        std::cout << "-------------------------\n";
+
+        typedef output_iterator<char>::type outiter_type;
+        typedef mini_xml_generator<outiter_type> mini_xml_generator;
+
+        mini_xml_generator gen;                     //  Our grammar definition
+        karma::grammar<mini_xml_generator> xmlout(gen, gen.xml); // Our grammar
+
+        std::string generated;
+        bool r = generate_delimited(output_iterator<char>::call(generated), 
+                    xmlout(ast), space);
+
+        if (r)
+            std::cout << generated << std::endl;
+        return 0;
+    }
+    else
+    {
+        std::string::const_iterator some = iter+30;
+        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;
+    }
+}
+
+
Added: trunk/libs/spirit/example/qi/mini_xml_samples/1.xml
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_xml_samples/1.xml	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1 @@
+<foo></foo>
\ No newline at end of file
Added: trunk/libs/spirit/example/qi/mini_xml_samples/2.xml
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_xml_samples/2.xml	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1 @@
+<foo><bar></bar></foo>
\ No newline at end of file
Added: trunk/libs/spirit/example/qi/mini_xml_samples/3.xml
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/mini_xml_samples/3.xml	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,5 @@
+<foo>
+    <bar>bar 1</bar>
+    <bar>bar 2</bar>
+    <bar>bar 3</bar>
+</foo>
\ No newline at end of file
Added: trunk/libs/spirit/example/qi/num_list.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/num_list.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,98 @@
+/*=============================================================================
+    Copyright (c) 2002-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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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/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>
+
+using namespace boost::phoenix;
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our number list compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+{
+    bool r = phrase_parse(first, last,
+
+        //  Begin grammar
+        (
+            double_[push_back(ref(v), _1)]
+                >> *(',' >> double_[push_back(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 (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;
+}
+
+
Added: trunk/libs/spirit/example/qi/num_list2.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/num_list2.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,97 @@
+/*=============================================================================
+    Copyright (c) 2002-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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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/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>
+
+using namespace boost::phoenix;
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our number list compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+{
+    bool r = phrase_parse(first, last,
+
+        //  Begin grammar
+        (
+            double_[push_back(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 (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;
+}
+
+
Added: trunk/libs/spirit/example/qi/num_list3.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/num_list3.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,97 @@
+/*=============================================================================
+    Copyright (c) 2002-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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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/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>
+
+using namespace boost::phoenix;
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our number list compiler
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+{
+    bool r = phrase_parse(first, last,
+
+        //  Begin grammar
+        (
+            double_ % ','
+        )
+        ,
+        //  End grammar
+
+        v, 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 (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;
+}
+
+
Added: trunk/libs/spirit/example/qi/roman.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/roman.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,168 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  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/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+using boost::phoenix::ref;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Parse roman hundreds (100..900) numerals using the symbol table.
+//  Notice that the data associated with each slot is passed
+//  to attached semantic actions.
+///////////////////////////////////////////////////////////////////////////////
+struct hundreds_ : 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.
+///////////////////////////////////////////////////////////////////////////////
+struct tens_ : 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.
+///////////////////////////////////////////////////////////////////////////////
+struct ones_ : 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
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct roman : grammar_def<Iterator, unsigned()>
+{
+    roman()
+    {
+        start
+            =   +char_('M') [_val += 1000]
+            ||  hundreds    [_val += _1]
+            ||  tens        [_val += _1]
+            ||  ones        [_val += _1];
+
+        //  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! :-)
+    }
+
+    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 roman<iterator_type> roman;
+
+    roman def; //  Our grammar definition
+    grammar<roman> roman_parser(def); // 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();
+        bool r = parse(iter, end, roman_parser[ref(result) = _1]);
+
+        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;
+}
+
+
Added: trunk/libs/spirit/example/qi/sum.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/sum.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,92 @@
+/*=============================================================================
+    Copyright (c) 2002-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)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+//  A parser for summing a comma-separated list of numbers using phoenix.
+//
+//  [ JDG June 28, 2002 ]   spirit1
+//  [ JDG March 24, 2007 ]  spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+using namespace boost::phoenix;
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+///////////////////////////////////////////////////////////////////////////////
+//  Our adder
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+bool adder(Iterator first, Iterator last, double& n)
+{
+    bool r = 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 (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;
+}
+
+
Added: trunk/libs/spirit/index.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/index.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+  </head>
+  <body>
+    Automatic redirection failed, click this 
+    link  <hr>
+    <p>© Copyright Beman Dawes, 2001</p>
+    <p>Distributed under the Boost Software License, Version 1.0. (See 
+    accompanying file <a href="../../LICENSE_1_0.txt">
+    LICENSE_1_0.txt</a> or copy at
+    www.boost.org/LICENSE_1_0.txt)</p>
+  </body>
+</html>
\ No newline at end of file
Added: trunk/libs/spirit/phoenix/doc/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/Jamfile.v2	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,12 @@
+project boost/libs/spirit/doc/phoenix/doc ;
+import boostbook : boostbook ;
+using quickbook ;
+
+boostbook quickbook
+    :
+        users_manual.qbk
+    :
+        <xsl:param>boost.root=../../../../..
+        <xsl:param>boost.libraries=../../../../libraries.htm
+    ;
+
Added: trunk/libs/spirit/phoenix/doc/html/boostbook.css
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/boostbook.css	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,511 @@
+/*=============================================================================
+    Copyright (c) 2004 Joel de Guzman
+    http://spirit.sourceforge.net/
+
+    Use, modification and distribution is subject to the Boost Software
+    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+    http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+/*=============================================================================
+    Body defaults
+=============================================================================*/
+
+    body 
+    {
+        margin: 1em;
+        font-family: sans-serif;
+    }
+
+/*=============================================================================
+    Paragraphs
+=============================================================================*/
+
+    p 
+    {
+        text-align: left;
+        font-size: 10pt; 
+        line-height: 1.15;
+    }
+
+/*=============================================================================
+    Program listings
+=============================================================================*/
+
+    /* Code on paragraphs */
+    p tt.computeroutput
+    {
+        font-size: 9pt;
+    }
+
+    pre.synopsis
+    {
+        font-size: 90%;
+        margin: 1pc 4% 0pc 4%;
+        padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+    }
+
+    .programlisting, 
+    .screen
+    {
+        font-size: 9pt;
+        display: block;
+        margin: 1pc 4% 0pc 4%;
+        padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+    }
+
+    /* Program listings in tables don't get borders */
+    td .programlisting, 
+    td .screen
+    {
+        margin: 0pc 0pc 0pc 0pc;
+        padding:  0pc 0pc 0pc 0pc;
+    }
+
+/*=============================================================================
+    Headings
+=============================================================================*/
+
+    h1, h2, h3, h4, h5, h6 
+    { 
+        text-align: left; 
+        margin: 1em 0em 0.5em 0em;
+        font-weight: bold;
+    }
+
+    h1 { font: 140% }
+    h2 { font: bold 140% }
+    h3 { font: bold 130% }
+    h4 { font: bold 120% }
+    h5 { font: italic 110% }
+    h6 { font: italic 100% }
+
+    /* Top page titles */
+    title, 
+    h1.title, 
+    h2.title
+    h3.title, 
+    h4.title, 
+    h5.title, 
+    h6.title, 
+    .refentrytitle
+    {
+        font-weight: bold;
+        margin-bottom: 1pc;
+    }
+
+    h1.title { font-size: 140% }
+    h2.title { font-size: 140% }
+    h3.title { font-size: 130% }
+    h4.title { font-size: 120% }
+    h5.title { font-size: 110% }
+    h6.title { font-size: 100% }
+
+    .section h1 
+    {
+        margin: 0em 0em 0.5em 0em;
+        font-size: 140%;
+    }
+
+    .section h2 { font-size: 140% }
+    .section h3 { font-size: 130% }
+    .section h4 { font-size: 120% }
+    .section h5 { font-size: 110% }
+    .section h6 { font-size: 100% }
+
+    /* Code on titles */
+    h1 tt.computeroutput { font-size: 140% }
+    h2 tt.computeroutput { font-size: 140% }
+    h3 tt.computeroutput { font-size: 130% }
+    h4 tt.computeroutput { font-size: 120% }
+    h5 tt.computeroutput { font-size: 110% }
+    h6 tt.computeroutput { font-size: 100% }
+
+/*=============================================================================
+    Author
+=============================================================================*/
+
+    h3.author 
+    { 
+        font-size: 100% 
+    }
+
+/*=============================================================================
+    Lists
+=============================================================================*/
+
+    li
+    {
+        font-size: 10pt;
+        line-height: 1.3;
+    }
+    
+    /* Unordered lists */
+    ul 
+    {
+        text-align: left;
+    }
+    
+    /* Ordered lists */
+    ol 
+    {
+        text-align: left;
+    }
+
+/*=============================================================================
+    Links
+=============================================================================*/
+
+    a
+    {
+        text-decoration: none; /* no underline */
+    }
+    
+    a:hover
+    {
+        text-decoration: underline;
+    }
+
+/*=============================================================================
+    Spirit style navigation
+=============================================================================*/
+
+    .spirit-nav
+    {
+        text-align: right;
+    }
+    
+    .spirit-nav a
+    {
+        color: white;
+        padding-left: 0.5em;
+    }
+    
+    .spirit-nav img
+    {
+        border-width: 0px;
+    }
+
+/*=============================================================================
+    Table of contents
+=============================================================================*/
+
+    .toc
+    {
+       margin: 1pc 4% 0pc 4%;
+       padding: 0.1pc 1pc 0.1pc 1pc;
+       font-size: 80%; 
+       line-height: 1.15;
+    }
+    
+    .boost-toc
+    {
+       float: right;
+       padding: 0.5pc;
+    }
+
+/*=============================================================================
+    Tables
+=============================================================================*/
+
+    .table-title, 
+    div.table p.title
+    {
+        margin-left: 4%;
+        padding-right: 0.5em; 
+        padding-left: 0.5em;
+    }
+    
+    .informaltable table, 
+    .table table
+    {
+        width: 92%;
+        margin-left: 4%;
+        margin-right: 4%;
+    }
+    
+    div.informaltable table, 
+    div.table table
+    {
+        padding: 4px;
+    }
+    
+    /* Table Cells */
+    div.informaltable table tr td, 
+    div.table table tr td
+    {
+        padding: 0.5em;
+        text-align: left;
+        font-size: 9pt;
+    }
+
+    div.informaltable table tr th, 
+    div.table table tr th
+    {
+        padding: 0.5em 0.5em 0.5em 0.5em;
+        border: 1pt solid white;
+        font-size: 80%;
+    }
+
+/*=============================================================================
+    Blurbs
+=============================================================================*/
+
+    div.note,
+    div.tip,
+    div.important,
+    div.caution,
+    div.warning,
+    p.blurb
+    {
+        font-size: 9pt; /* A little bit smaller than the main text */
+        line-height: 1.2;
+        display: block;
+        margin: 1pc 4% 0pc 4%;
+        padding: 0.5pc 0.5pc 0.5pc 0.5pc;
+    }
+    
+    p.blurb img
+    {
+        padding: 1pt;
+    }
+
+/*=============================================================================
+    Variable Lists
+=============================================================================*/
+
+    /* Make the terms in definition lists bold */
+    div.variablelist dl dt,
+    span.term
+    {
+        font-weight: bold;
+        font-size: 10pt;
+    }
+
+    div.variablelist table tbody tr td
+    {
+        text-align: left;
+        vertical-align: top;
+        padding: 0em 2em 0em 0em;
+        font-size: 10pt;
+        margin: 0em 0em 0.5em 0em;
+        line-height: 1;
+    }
+
+    div.variablelist dl dt
+    {
+        margin-bottom: 0.2em;
+    }
+
+    div.variablelist dl dd
+    {
+        margin: 0em 0em 0.5em 2em;
+        font-size: 10pt;
+    }
+
+    div.variablelist table tbody tr td p,
+    div.variablelist dl dd p
+    {
+        margin: 0em 0em 0.5em 0em;
+        line-height: 1;
+    }
+
+/*=============================================================================
+    Misc
+=============================================================================*/
+
+    /* Title of books and articles in bibliographies */
+    span.title
+    {
+        font-style: italic;
+    }
+
+    span.underline
+    {
+        text-decoration: underline;
+    }
+
+    span.strikethrough
+    {
+        text-decoration: line-through;
+    }
+
+    /* Copyright, Legal Notice */
+    div div.legalnotice p
+    {
+        text-align: left
+    }
+
+/*=============================================================================
+    Colors
+=============================================================================*/
+
+    @media screen
+    {
+    /* Links */
+        a
+        {
+            color: #005a9c;
+        }
+    
+        a:visited
+        {
+            color: #9c5a9c;
+        }
+
+        h1 a, h2 a, h3 a, h4 a, h5 a, h6 a,
+        h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover,
+        h1 a:visited, h2 a:visited, h3 a:visited, h4 a:visited, h5 a:visited, h6 a:visited
+        {
+            text-decoration: none; /* no underline */
+            color: #000000;
+        }
+    
+    /* Syntax Highlighting */
+        .keyword        { color: #0000AA; }
+        .identifier     { color: #000000; }
+        .special        { color: #707070; }
+        .preprocessor   { color: #402080; }
+        .char           { color: teal; }
+        .comment        { color: #800000; }
+        .string         { color: teal; }
+        .number         { color: teal; }
+        .white_bkd      { background-color: #FFFFFF; }
+        .dk_grey_bkd    { background-color: #999999; }
+    
+    /* Copyright, Legal Notice */
+        .copyright      
+        { 
+            color: #666666; 
+            font-size: small; 
+        }
+    
+        div div.legalnotice p
+        {
+            color: #666666;
+        }
+    
+    /* Program listing */
+        pre.synopsis
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+        .programlisting, 
+        .screen
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+        td .programlisting, 
+        td .screen
+        {
+            border: 0px solid #DCDCDC;
+        }
+    
+    /* Blurbs */
+        div.note,
+        div.tip,
+        div.important,
+        div.caution,
+        div.warning,
+        p.blurb
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+    /* Table of contents */
+        .toc
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+    /* Tables */
+        div.informaltable table tr td, 
+        div.table table tr td
+        {
+            border: 1px solid #DCDCDC;
+        }
+    
+        div.informaltable table tr th, 
+        div.table table tr th
+        {
+            background-color: #F0F0F0;
+            border: 1px solid #DCDCDC;
+        }
+    
+    /* Misc */
+        span.highlight
+        {
+            color: #00A000;
+        }
+    }
+    
+    @media print
+    {
+    /* Links */
+        a
+        {
+            color: black;
+        }
+    
+        a:visited
+        {
+            color: black;
+        }
+    
+        .spirit-nav
+        {
+            display: none;
+        }
+    
+    /* Program listing */
+        pre.synopsis
+        {
+            border: 1px solid gray;
+        }
+    
+        .programlisting, 
+        .screen
+        {
+            border: 1px solid gray;
+        }
+    
+        td .programlisting, 
+        td .screen
+        {
+            border: 0px solid #DCDCDC;
+        }
+    
+    /* Table of contents */
+        .toc
+        {
+            border: 1px solid gray;
+        }
+    
+        .informaltable table, 
+        .table table
+        {
+            border: 1px solid gray;
+            border-collapse: collapse;
+        }
+    
+    /* Tables */
+        div.informaltable table tr td, 
+        div.table table tr td
+        {
+            border: 1px solid gray;
+        }
+    
+        div.informaltable table tr th, 
+        div.table table tr th
+        {
+            border: 1px solid gray;
+        }
+    
+    /* Misc */
+        span.highlight
+        {
+            font-weight: bold;
+        }
+    }
Added: trunk/libs/spirit/phoenix/doc/html/images/add2.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/add2_call.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/adder.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/alert.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/banner.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/fbox.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/funnel_in.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/funnel_out.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/home.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/lambda_cpp.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/next.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/note.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/organization.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/prev.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/smiley.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/tip.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/images/up.png
==============================================================================
Binary file. No diff available.
Added: trunk/libs/spirit/phoenix/doc/html/index.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/index.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,224 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Chapter 1. Phoenix 2.0</title>
+<link rel="stylesheet" href="boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="next" href="phoenix/introduction.html" title="Introduction">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav"><a accesskey="n" href="phoenix/introduction.html"><img src="images/next.png" alt="Next"></a></div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div>
+<div><h2 class="title">
+<a name="phoenix"></a>Chapter 1. Phoenix 2.0</h2></div>
+<div><div class="author"><h3 class="author">
+<span class="firstname">Joel</span> <span class="surname">de Guzman</span>
+</h3></div></div>
+<div><div class="author"><h3 class="author">
+<span class="firstname">Dan</span> <span class="surname">Marsden</span>
+</h3></div></div>
+<div><p class="copyright">Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</p></div>
+<div><div class="legalnotice">
+<a name="id442840"></a><p>
+        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)
+      </p>
+</div></div>
+</div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="section">Preface</span></dt>
+<dt><span class="section">Introduction</span></dt>
+<dt><span class="section">Starter Kit</span></dt>
+<dd><dl>
+<dt><span class="section">Values</span></dt>
+<dt><span class="section">References</span></dt>
+<dt><span class="section">Arguments</span></dt>
+<dt><span class="section">Composites</span></dt>
+<dt><span class="section">Lazy Operators</span></dt>
+<dt><span class="section">Lazy Statements</span></dt>
+<dt><span class="section">Construct, New, Delete, Casts</span></dt>
+<dt><span class="section">Lazy Functions</span></dt>
+<dt><span class="section">More</span></dt>
+</dl></dd>
+<dt><span class="section">Basics</span></dt>
+<dt><span class="section">Organization</span></dt>
+<dt><span class="section">Actors</span></dt>
+<dt><span class="section">Primitives</span></dt>
+<dd><dl>
+<dt><span class="section">Arguments</span></dt>
+<dt><span class="section">Values</span></dt>
+<dt><span class="section">References</span></dt>
+<dt><span class="section">Constant References</span></dt>
+<dt><span class="section">Nothing</span></dt>
+</dl></dd>
+<dt><span class="section">Composite</span></dt>
+<dd><dl>
+<dt><span class="section">Function</span></dt>
+<dt><span class="section">Operator</span></dt>
+<dt><span class="section">Statement</span></dt>
+<dt><span class="section">Object</span></dt>
+<dt><span class="section">Scope</span></dt>
+<dt><span class="section">Bind</span></dt>
+</dl></dd>
+<dt><span class="section">Container</span></dt>
+<dt><span class="section">Algorithm</span></dt>
+<dt><span class="section">Inside Phoenix</span></dt>
+<dd><dl>
+<dt><span class="section">Actors In Detail</span></dt>
+<dt><span class="section">Actor Example</span></dt>
+<dt><span class="section">Composites In Detail</span></dt>
+<dt><span class="section">Composing</span></dt>
+<dt><span class="section">Extending</span></dt>
+</dl></dd>
+<dt><span class="section">Wrap Up</span></dt>
+<dt><span class="section">Acknowledgement</span></dt>
+<dt><span class="section">References</span></dt>
+</dl>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.preface"></a>Preface</h2></div></div></div>
+<div class="blockquote"><blockquote class="blockquote"><p>
+        <span class="emphasis"><em>Functional programming is so called because a program consists
+        entirely of functions. The main program itself is written as a function which
+        receives the program's input as its argument and delivers the program's output
+        as its result. Typically the main function is defined in terms of other functions,
+        which in turn are defined in terms of still more functions until at the bottom
+        level the functions are language primitives.</em></span>
+      </p></blockquote></div>
+<div class="blockquote"><blockquote class="blockquote"><p>
+        <span class="bold"><b>John Hughes</b></span>-- <span class="emphasis"><em>Why Functional Programming
+        Matters</em></span>
+      </p></blockquote></div>
+<p>
+      <span class="inlinemediaobject"><img src="images/lambda_cpp.png" alt="lambda_cpp"></span>
+    </p>
+<a name="phoenix.preface.description"></a><h2>
+<a name="id372685"></a>
+      Description
+    </h2>
+<p>
+      Phoenix enables Functional Programming (FP) in C++. The design and implementation
+      of Phoenix is highly influenced by FC++
+      by Yannis Smaragdakis and Brian McNamara and the BLL
+      (Boost Lambda Library) by Jaakko Jaarvi and Gary Powell. Phoenix is a blend
+      of FC++ and BLL using the implementation techniques used in the Spirit
+      inline parser. Phoenix version 2, this version, will probably be the last release
+      of the library. Phoenix v2 will be the basis of the Phoenix and BLL
+      merger.
+    </p>
+<p>
+      Phoenix is a header only library. It is extremely modular by design. One can
+      extract and use only a small subset of the full library, literally tearing
+      the library into small pieces, without fear that the pieces won't work anymore.
+      The library is organized in highly independent modules and layers.
+    </p>
+<a name="phoenix.preface.how_to_use_this_manual"></a><h2>
+<a name="id372541"></a>
+      How to use this manual
+    </h2>
+<p>
+      The Phoenix library is organized in logical modules. This documentation provides
+      a user's guide and reference for each module in the library. A simple and clear
+      code example is worth a hundred lines of documentation; therefore, the user's
+      guide is presented with abundant examples annotated and explained in step-wise
+      manner. The user's guide is based on examples: lots of them.
+    </p>
+<p>
+      As much as possible, forward information (i.e. citing a specific piece of information
+      that has not yet been discussed) is avoided in the user's manual portion of
+      each module. In many cases, though, it is unavoidable that advanced but related
+      topics not be interspersed with the normal flow of discussion. To alleviate
+      this problem, topics categorized as "advanced" may be skipped at
+      first reading.
+    </p>
+<p>
+      Some icons are used to mark certain topics indicative of their relevance. These
+      icons precede some text to indicate:
+    </p>
+<div class="informaltable">
+<h4>
+<a name="id372571"></a>
+        <span class="table-title">Icons</span>
+      </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Icon</th>
+<th>Name</th>
+<th>Meaning</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><span class="inlinemediaobject"><img src="images/note.png" alt="note"></span></td>
+<td>Note</td>
+<td>Information provided
+            is auxiliary but will give the reader a deeper insight into a specific
+            topic. May be skipped.</td>
+</tr>
+<tr>
+<td><span class="inlinemediaobject"><img src="images/alert.png" alt="alert"></span></td>
+<td>Alert</td>
+<td>Information provided
+            is of utmost importance.</td>
+</tr>
+<tr>
+<td><span class="inlinemediaobject"><img src="images/tip.png" alt="tip"></span></td>
+<td>Tip</td>
+<td>A potentially useful
+            and helpful piece of information.</td>
+</tr>
+</tbody>
+</table>
+</div>
+<p>
+      This documentation is automatically generated by Spirit QuickBook documentation
+      tool. QuickBook can be found in the <a href="http://spirit.sourceforge.net/repository/applications/show_contents.php" target="_top">Spirit
+      Repository</a>.
+    </p>
+<a name="phoenix.preface.support"></a><h2>
+<a name="id374497"></a>
+      Support
+    </h2>
+<p>
+      Please direct all questions to Spirit's mailing list. You can subscribe to
+      the <a href="https://lists.sourceforge.net/lists/listinfo/spirit-general" target="_top">Spirit
+      Mailing List</a>. The mailing list has a searchable archive. A search link
+      to this archive is provided in Spirit's
+      home page. You may also read and post messages to the mailing list through
+      <a href="news://news.gmane.org/gmane.comp.spirit.general" target="_top">Spirit General
+      NNTP news portal</a> (thanks to Gmane).
+      The news group mirrors the mailing list. Here is a link to the archives: http://news.gmane.org/gmane.comp.parsers.spirit.general.
+    </p>
+<a name="phoenix.preface._emphasis_role__bold___emphasis____to_my_dear_daughter__phoenix__emphasis___emphasis_"></a><h2>
+<a name="id374555"></a>
+      <span class="bold"><b><span class="emphasis"><em>...To my dear daughter, Phoenix</em></span></b></span>
+    </h2>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"><small><p>Last revised: June 09, 2006 at 13:58:55 GMT</p></small></td>
+<td align="right"><small></small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav"><a accesskey="n" href="phoenix/introduction.html"><img src="images/next.png" alt="Next"></a></div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/acknowledgement.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/acknowledgement.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,87 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Acknowledgement</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="wrap_up.html" title="Wrap Up">
+<link rel="next" href="references.html" title="References">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="wrap_up.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="references.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.acknowledgement"></a>Acknowledgement</h2></div></div></div>
+<div class="orderedlist"><ol type="1">
+<li>
+        Hartmut Kaiser implemented the original lazy casts and constructors based
+        on his original work on Spirit SE "semantic expressions" (the precursor
+        to Phoenix).
+      </li>
+<li>
+        Angus Leeming implemented the container functions on Phoenix-1 which I then
+        ported to Phoenix-2.
+      </li>
+<li>
+        Daniel Wallin helped with the scope module, local variables, let and lambda
+        and the algorithms. I frequently discuss design issues with Daniel on Yahoo
+        Messenger.
+      </li>
+<li>
+        Jaakko Jarvi. DA Lambda MAN!
+      </li>
+<li>
+        Dave Abrahams, for his constant presence, wherever, whenever.
+      </li>
+<li>
+        Aleksey Gurtovoy, DA MPL MAN!
+      </li>
+<li>
+        Doug Gregor, always a source of inpiration.
+      </li>
+<li>
+        Dan Marsden, did almost all the work in bringing Phoenix-2 out the door.
+      </li>
+<li>
+        Eric Niebler did a 2.0 pre-release review and wrote some range related code
+        that Phoenix stole and used in the algorithms.
+      </li>
+<li>
+        Thorsten Ottosen; Eric's range_ex code began life as "container_algo"
+        in the old boost sandbox, by Thorsten in 2002-2003.
+      </li>
+<li>
+        Jeremy Siek, even prior to Thorsten, in 2001, started the "container_algo".
+      </li>
+<li>
+        Vladimir Prus wrote the mutating algorithms code from the Boost Wiki.
+      </li>
+<li>
+        Daryle Walker did a 2.0 pre-release review.
+      </li>
+</ol></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="wrap_up.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="references.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/actors.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/actors.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,82 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Actors</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="organization.html" title="Organization">
+<link rel="next" href="primitives.html" title="Primitives">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="organization.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="primitives.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.actors"></a>Actors</h2></div></div></div>
+<p>
+      The <tt class="computeroutput"><span class="identifier">Actor</span></tt> is the main concept
+      behind the library. Actors are function objects. An actor can accept 0 to
+      <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt> arguments.
+    </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> You can set <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt>,
+            the predefined maximum arity an actor can take. By default, <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt> is set to 10.</td></tr></tbody>
+</table></div>
+<p>
+      Phoenix supplies an <tt class="computeroutput"><span class="identifier">actor</span></tt> class
+      template whose specializations model the <tt class="computeroutput"><span class="identifier">Actor</span></tt>
+      concept. <tt class="computeroutput"><span class="identifier">actor</span></tt> has one template
+      parameter, <tt class="computeroutput"><span class="identifier">Eval</span></tt>, that supplies
+      the smarts to evaluate the resulting function.
+    </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Eval</span><span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">actor</span> <span class="special">:</span> <span class="identifier">Eval</span>
+<span class="special">{</span>
+    <span class="identifier">return_type</span>
+    <span class="keyword">operator</span><span class="special">()()</span> <span class="keyword">const</span><span class="special">;</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">></span>
+    <span class="identifier">return_type</span>
+    <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">></span>
+    <span class="identifier">return_type</span>
+    <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&</span> <span class="identifier">_1</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+
+    <span class="comment">//...
+</span><span class="special">};</span>
+</pre>
+<p>
+      The actor class accepts the arguments through a set of function call operators
+      for 0 to <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt> arities
+      (Don't worry about the details, for now. Note, for example, that we skimp over
+      the details regarding <tt class="computeroutput"><span class="identifier">return_type</span></tt>).
+      The arguments are then forwarded to the actor's <tt class="computeroutput"><span class="identifier">Eval</span></tt>
+      for evaluation.
+    </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="organization.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="primitives.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/algorithm.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/algorithm.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,408 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Algorithm</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="container.html" title="Container">
+<link rel="next" href="inside_phoenix.html" title="Inside Phoenix">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="container.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="inside_phoenix.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.algorithm"></a>Algorithm</h2></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+      The algorithm module provides wrappers for the standard algorithms in the
+      <tt class="computeroutput"><span class="special"><</span><span class="identifier">algorithm</span><span class="special">></span></tt> and <tt class="computeroutput"><span class="special"><</span><span class="identifier">numeric</span><span class="special">></span></tt>
+      headers.
+    </p>
+<p>
+      The algorithms are divided into the categories iteration, transformation and
+      querying, modelling the Boost.MPL
+      library. The different algorithm classes can be included using the headers:
+    </p>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">stl</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">/</span><span class="identifier">iteration</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">stl</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">/</span><span class="identifier">transformation</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">stl</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">/</span><span class="identifier">querying</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+      The functions of the algorithm module take ranges as arguments where appropriate.
+      This is different to the standard library, but easy enough to pick up. Ranges
+      are described in detail in the Boost.Range
+      library.
+    </p>
+<p>
+      For example, using the standard copy algorithm to copy between 2 arrays:
+    </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">array</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">};</span>
+<span class="keyword">int</span> <span class="identifier">output</span><span class="special">[</span><span class="number">3</span><span class="special">];</span>
+<span class="identifier">std</span><span class="special">::</span><span class="identifier">copy</span><span class="special">(</span><span class="identifier">array</span><span class="special">,</span> <span class="identifier">array</span> <span class="special">+</span> <span class="number">3</span><span class="special">,</span> <span class="identifier">output</span><span class="special">);</span> <span class="comment">// We have to provide iterators 
+</span>                                     <span class="comment">// to both the start and end of array
+</span></pre>
+<p>
+      The analogous code using the phoenix algorithm module is:
+    </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">array</span><span class="special">[]</span> <span class="special">=</span> <span class="special">{</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">};</span>
+<span class="keyword">int</span> <span class="identifier">output</span><span class="special">[</span><span class="number">3</span><span class="special">];</span>
+<span class="identifier">copy</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)(</span><span class="identifier">array</span><span class="special">,</span> <span class="identifier">output</span><span class="special">);</span> <span class="comment">// Notice only 2 arguments, the end of 
+</span>                                 <span class="comment">// array is established automatically
+</span></pre>
+<p>
+      The Boost.Range
+      library provides support for standard containers, strings and arrays, and can
+      be extended to support additional types.
+    </p>
+<p>
+      The following tables describe the different categories of algorithms, and their
+      semantics.
+    </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Arguments in brackets denote optional parameters.</td></tr></tbody>
+</table></div>
+<div class="informaltable">
+<h4>
+<a name="id471284"></a>
+        <span class="table-title">Iteration Algorithms</span>
+      </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Function</th>
+<th>stl Semantics</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">accumulate</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">accumulate</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="informaltable">
+<h4>
+<a name="id471564"></a>
+        <span class="table-title">Querying Algorithms</span>
+      </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Function</th>
+<th>stl Semantics</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">find</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">find</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">find_if</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">find_if</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">find_end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">find_end</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">adjacent_find</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">adjacent_find</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">count</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">count</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">count_if</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">count_if</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">mismatch</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">i</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">mismatch</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">i</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">equal</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">i</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">equal</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">i</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">search</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">search</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">lower_bound</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">lower_bound</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">upper_bound</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">upper_bound</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">equal_range</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">equal_range</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">binary_search</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">binary_search</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">includes</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">includes</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">min_element</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">min_element</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">max_element</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">max_element</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">lexicographical_compare</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">lexicographical_compare</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="informaltable">
+<h4>
+<a name="id473941"></a>
+        <span class="table-title">Transformation Algorithms</span>
+      </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Function</th>
+<th>stl Semantics</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">copy</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">copy</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">copy_backward</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">copy_backward</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">transform</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">transform</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">transform</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">i</span><span class="special">,</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">transform</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">i</span><span class="special">,</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">replace</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">replace</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">replace_if</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">replace</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">replace_copy</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">replace_copy</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">replace_copy_if</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">replace_copy_if</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">fill</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">fill</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">fill_n</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">fill_n</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">generate</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">generate</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">generate_n</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">generate_n</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">remove</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">remove</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">remove_if</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">remove_if</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">remove_copy</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">remove_copy</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">a</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">remove_copy_if</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">remove_copy_if</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">unique</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">unique</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">unique_copy</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">unique_copy</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">reverse</span><span class="special">(</span><span class="identifier">r</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">reverse</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">))</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">reverse_copy</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">reverse_copy</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">rotate</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">m</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">rotate</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">m</span><span class="special">,</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">))</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">rotate_copy</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">m</span><span class="special">,</span> <span class="identifier">o</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">rotate_copy</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">m</span><span class="special">,</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">random_shuffle</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">random_shuffle</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">partition</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">partition</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">stable_partition</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">stable_partition</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">f</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">sort</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">sort</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">stable_sort</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">stable_sort</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">partial_sort</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">m</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">partial_sort</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">m</span><span class="special">,</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">partial_sort_copy</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">partial_sort_copy</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">nth_element</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">n</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">nth_element</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">merge</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">merge</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">inplace_merge</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">m</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">inplace_merge</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">m</span><span class="special">,</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">set_union</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">set_union</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">set_intersection</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">set_intersection</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">set_difference</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">set_difference</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">set_symmetric_difference</span><span class="special">(</span><span class="identifier">r1</span><span class="special">,</span> <span class="identifier">r2</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">set_symmetric_difference</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r1</span><span class="special">),</span> <span class="identifier">begin</span><span class="special">(</span><span class="identifier">r2</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r2</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">push_heap</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">push_heap</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">pop_heap</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">pop_heap</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">make_heap</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">make_heap</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">sort_heap</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">sort_heap</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">next_permutation</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">next_permutation</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">prev_permutation</span><span class="special">(</span><span class="identifier">r</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">prev_permutation</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">)[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">inner_product</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">,</span> <span class="identifier">a</span><span class="special">[,</span> <span class="identifier">f1</span><span class="special">,</span> <span class="identifier">f2</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">inner_product</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f1</span><span class="special">,</span> <span class="identifier">f2</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">partial_sum</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">partial_sum</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">adjacent_difference</span><span class="special">(</span><span class="identifier">r</span><span class="special">,</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">adjacent_difference</span><span class="special">(</span><span class="identifier">begin</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">end</span><span class="special">(</span><span class="identifier">r</span><span class="special">),</span> <span class="identifier">o</span><span class="special">[,</span> <span class="identifier">f</span><span class="special">])</span></tt></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="container.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="inside_phoenix.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/basics.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/basics.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,243 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Basics</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="starter_kit.html" title="Starter Kit">
+<link rel="next" href="organization.html" title="Organization">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="starter_kit.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="organization.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.basics"></a>Basics</h2></div></div></div>
+<p>
+      Almost everything is a function in the Phoenix library that can be evaluated
+      as <tt class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="identifier">a1</span><span class="special">,</span> <span class="identifier">a2</span><span class="special">,</span> <span class="special">...,</span> a<span class="emphasis"><em>n</em></span><span class="special">)</span></tt>,
+      where <span class="emphasis"><em>n</em></span> is the function's arity, or number of arguments
+      that the function expects. Operators are also functions. For example, <tt class="computeroutput"><span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span></tt> is just a function with arity == 2 (or
+      binary). <tt class="computeroutput"><span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span></tt> is the same as <tt class="computeroutput"><span class="identifier">add</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span></tt>, <tt class="computeroutput"><span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span> <span class="special">+</span> <span class="identifier">c</span></tt> is the same as <tt class="computeroutput"><span class="identifier">add</span><span class="special">(</span><span class="identifier">add</span><span class="special">(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">),</span> <span class="identifier">c</span><span class="special">)</span></tt>.
+    </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> Amusingly, functions may even return functions.
+            We shall see what this means in a short while.</td></tr></tbody>
+</table></div>
+<a name="phoenix.basics.partial_function_application"></a><h2>
+<a name="id446467"></a>
+      Partial Function Application
+    </h2>
+<p>
+      Think of a function as a black box. You pass arguments and it returns something
+      back. The figure below depicts the typical scenario.
+    </p>
+<p>
+      <span class="inlinemediaobject"><img src="../images/fbox.png" alt="fbox"></span>
+    </p>
+<p>
+      A fully evaluated function is one in which all the arguments are given. All
+      functions in plain C++ are fully evaluated. When you call the <tt class="computeroutput"><span class="identifier">sin</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></tt> function, you have to pass a number x. The
+      function will return a result in return: the sin of x. When you call the <tt class="computeroutput"><span class="identifier">add</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">)</span></tt> function, you have to pass two numbers x and
+      y. The function will return the sum of the two numbers. The figure below is
+      a fully evaluated <tt class="computeroutput"><span class="identifier">add</span></tt> function.
+    </p>
+<p>
+      <span class="inlinemediaobject"><img src="../images/adder.png" alt="adder"></span>
+    </p>
+<p>
+      A partially applied function, on the other hand, is one in which not all the
+      arguments are supplied. If we are able to partially apply the function <tt class="computeroutput"><span class="identifier">add</span></tt> above, we may pass only the first argument.
+      In doing so, the function does not have all the required information it needs
+      to perform its task to compute and return a result. What it returns instead
+      is another function, a lambda function --another black box. Unlike the original
+      <tt class="computeroutput"><span class="identifier">add</span></tt> function which has an arity
+      of 2, the resulting lambda function has an arity of 1. Why? because we already
+      supplied part of the input: <tt class="computeroutput"><span class="number">2</span></tt>
+    </p>
+<p>
+      <span class="inlinemediaobject"><img src="../images/add2.png" alt="add2"></span>
+    </p>
+<p>
+      Now, when we shove in a number into our lambda function, it will return 2 plus
+      whatever we pass in. The lambda function essentially remembers 1) the original
+      function, <tt class="computeroutput"><span class="identifier">add</span></tt>, and 2) the partial
+      input, 2. The figure below illustrates a case where we pass 3 to our lambda
+      function, which then returns 5:
+    </p>
+<p>
+      <span class="inlinemediaobject"><img src="../images/add2_call.png" alt="add2_call"></span>
+    </p>
+<p>
+      Obviously, partially applying the <tt class="computeroutput"><span class="identifier">add</span></tt>
+      function, as we see above, cannot be done directly in C++ where we are expected
+      to supply all the arguments that a function expects. That's where the Phoenix
+      library comes in. The library provides the facilities to do partial function
+      application.
+    </p>
+<a name="phoenix.basics.stl_and_higher_order_functions"></a><h2>
+<a name="id446722"></a>
+      STL and higher order functions
+    </h2>
+<p>
+      So, what's all the fuss? What makes partial function application so useful?
+      Recall our original example in the <a href="starter_kit.html" title="Starter Kit">previous
+      section</a>:
+    </p>
+<pre class="programlisting">
+<span class="identifier">find_if</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">)</span>
+</pre>
+<p>
+      The expression <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span></tt> evaluates to a lambda function. <tt class="computeroutput"><span class="identifier">arg1</span></tt> is a placeholder for an argument to
+      be supplied later. Hence, since there's only one unsupplied argument, the lambda
+      function has an arity 1. It just so happens that <tt class="computeroutput"><span class="identifier">find_if</span></tt>
+      supplies the unsupplied argument as it loops from <tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()</span></tt>
+      to <tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">()</span></tt>.
+    </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> Higher order functions are functions which can take
+            other functions as arguments, and may also return functions as results.
+            Higher order functions are functions that are treated like any other
+            objects and can be used as arguments and return values from functions.</td></tr></tbody>
+</table></div>
+<a name="phoenix.basics.lazy_evaluation"></a><h2>
+<a name="id446996"></a>
+      Lazy Evaluation
+    </h2>
+<p>
+      In Phoenix, to put it more accurately, function evaluation has two stages:
+    </p>
+<div class="orderedlist"><ol type="1">
+<li>
+        Partial application
+      </li>
+<li>
+        Final evaluation
+      </li>
+</ol></div>
+<p>
+      The first stage is handled by a set of generator functions. These are your
+      front ends (in the client's perspective). These generators create (through
+      partial function application), higher order functions that can be passed on
+      just like any other function pointer or function object. The second stage,
+      the actual function call, can be invoked or executed anytime in the future,
+      or not at all; hence <span class="emphasis"><em>"lazy"</em></span>.
+    </p>
+<p>
+      If we look more closely, the first step involves partial function application:
+    </p>
+<pre class="programlisting">
+<span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span>
+</pre>
+<p>
+      The second step is the actual function invocation (done inside the <tt class="computeroutput"><span class="identifier">find_if</span></tt> function. These are the back-ends
+      (often, the final invocation is never actually seen by the client). In our
+      example, the <tt class="computeroutput"><span class="identifier">find_if</span></tt>, if we
+      take a look inside, we'll see something like:
+    </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">class</span> <span class="identifier">InputIterator</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Predicate</span><span class="special">></span>
+<span class="identifier">InputIterator</span>
+<span class="identifier">find_if</span><span class="special">(</span><span class="identifier">InputIterator</span> <span class="identifier">first</span><span class="special">,</span> <span class="identifier">InputIterator</span> <span class="identifier">last</span><span class="special">,</span> <span class="identifier">Predicate</span> <span class="identifier">pred</span><span class="special">)</span>
+<span class="special">{</span>
+    <span class="keyword">while</span> <span class="special">(</span><span class="identifier">first</span> <span class="special">!=</span> <span class="identifier">last</span> <span class="special">&&</span> <span class="special">!</span><span class="identifier">pred</span><span class="special">(*</span><span class="identifier">first</span><span class="special">))</span>  <span class="comment">// <--- The lambda function is called here
+</span>        <span class="special">++</span><span class="identifier">first</span><span class="special">;</span>                            <span class="comment">//      passing in *first
+</span>    <span class="keyword">return</span> <span class="identifier">first</span><span class="special">;</span>
+<span class="special">}</span>
+</pre>
+<p>
+      Again, typically, we, as clients, see only the first step. However, in this
+      document and in the examples and tests provided, don't be surprised to see
+      the first and second steps juxtaposed in order to illustrate the complete semantics
+      of Phoenix expressions. Examples:
+    </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>
+<span class="keyword">int</span> <span class="identifier">y</span> <span class="special">=</span> <span class="number">2</span><span class="special">;</span>
+
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="special">(</span><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">)(</span><span class="identifier">x</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span> <span class="comment">// prints 1 or true
+</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="special">(</span><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">)(</span><span class="identifier">y</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span> <span class="comment">// prints 0 or false
+</span></pre>
+<a name="phoenix.basics.forwarding_function_problem"></a><h2>
+<a name="id447608"></a>
+      Forwarding Function Problem
+    </h2>
+<p>
+      Usually, we, as clients, write the call-back functions while libraries (such
+      as STL) provide the callee (e.g. <tt class="computeroutput"><span class="identifier">find_if</span></tt>).
+      In case the role is reversed, e.g. if you have to write an STL algorithm that
+      takes in a predicate, or develop a GUI library that accepts event handlers,
+      you have to be aware of a little known problem in C++ called the "<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm" target="_top">Forwarding
+      Function Problem</a>".
+    </p>
+<p>
+      Look again at the code above:
+    </p>
+<pre class="programlisting">
+<span class="special">(</span><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">)(</span><span class="identifier">x</span><span class="special">)</span>
+</pre>
+<p>
+      Notice that, in the second-stage (the final evaluation), we used a variable
+      <tt class="computeroutput"><span class="identifier">x</span></tt>. Be aware that the second
+      stage cannot accept non-const temporaries and literal constants. Hence, this
+      will fail:
+    </p>
+<pre class="programlisting">
+<span class="special">(</span><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">)(</span><span class="number">123</span><span class="special">)</span> <span class="comment">// Error!
+</span></pre>
+<p>
+      Disallowing non-const rvalues partially solves the "<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm" target="_top">Forwarding
+      Function Problem</a>" but prohibits code like above.
+    </p>
+<a name="phoenix.basics.polymorphic_functions"></a><h2>
+<a name="id447803"></a>
+      Polymorphic Functions
+    </h2>
+<p>
+      Unless otherwise noted, Phoenix generated functions are fully polymorphic.
+      For instance, the <tt class="computeroutput"><span class="identifier">add</span></tt> example
+      above can apply to integers, floating points, user defined complex numbers
+      or even strings. Example:
+    </p>
+<pre class="programlisting">
+<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">h</span><span class="special">(</span><span class="string">"Hello"</span><span class="special">);</span>
+<span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">w</span> <span class="special">=</span> <span class="string">" World"</span><span class="special">;</span>
+<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">r</span> <span class="special">=</span> <span class="identifier">add</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)(</span><span class="identifier">h</span><span class="special">,</span> <span class="identifier">w</span><span class="special">);</span>
+</pre>
+<p>
+      evaluates to <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">(</span><span class="string">"Hello
+      World"</span><span class="special">)</span></tt>. The observant
+      reader might notice that this function call in fact takes in heterogeneous
+      arguments where <tt class="computeroutput"><span class="identifier">arg1</span></tt> is of
+      type <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></tt> and <tt class="computeroutput"><span class="identifier">arg2</span></tt>
+      is of type <tt class="computeroutput"><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span></tt>. <tt class="computeroutput"><span class="identifier">add</span></tt>
+      still works because the C++ standard library allows the expression <tt class="computeroutput"><span class="identifier">a</span> <span class="special">+</span> <span class="identifier">b</span></tt> where <tt class="computeroutput"><span class="identifier">a</span></tt>
+      is a <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></tt> and <tt class="computeroutput"><span class="identifier">b</span></tt>
+      is a <tt class="computeroutput"><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span></tt>.
+    </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="starter_kit.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="organization.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/composite.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/composite.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,1534 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Composite</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="primitives.html" title="Primitives">
+<link rel="next" href="container.html" title="Container">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="primitives.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="container.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.composite"></a>Composite</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">Function</span></dt>
+<dt><span class="section">Operator</span></dt>
+<dt><span class="section">Statement</span></dt>
+<dt><span class="section">Object</span></dt>
+<dt><span class="section">Scope</span></dt>
+<dt><span class="section">Bind</span></dt>
+</dl></div>
+<p>
+      Actors may be combined in a multitude of ways to form composites. Composites
+      are actors that are composed of zero or more actors. Composition is hierarchical.
+      An element of the composite can be a primitive or again another composite.
+      The flexibility to arbitrarily compose hierarchical structures allows us to
+      form intricate constructions that model complex functions, statements and expressions.
+    </p>
+<p>
+      A composite is-a tuple of 0..N actors. N is the predefined maximum actors a
+      composite can take.
+    </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> You can set <tt class="computeroutput"><span class="identifier">PHOENIX_COMPOSITE_LIMIT</span></tt>,
+            the predefined maximum actors a composite can take. By default, <tt class="computeroutput"><span class="identifier">PHOENIX_COMPOSITE_LIMIT</span></tt> is set to
+            <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt> (See Actors).</td></tr></tbody>
+</table></div>
+<p>
+      As mentioned, each of the actors A0..AN can, in turn, be another composite,
+      since a composite is itself an actor. This makes the composite a recursive
+      structure. The actual evaluation is handled by a composite specific eval policy.
+    </p>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.composite.function"></a>Function</h3></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">function</span><span class="special">/</span><span class="identifier">function</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        The <tt class="computeroutput"><span class="identifier">function</span></tt> class template
+        provides a mechanism for implementing lazily evaluated functions. Syntactically,
+        a lazy function looks like an ordinary C/C++ function. The function call
+        looks familiar and feels the same as ordinary C++ functions. However, unlike
+        ordinary functions, the actual function execution is deferred.
+      </p>
+<p>
+        Unlike ordinary function pointers or functor objects that need to be explicitly
+        bound through the bind function (see Bind),
+        the argument types of these functions are automatically lazily bound.
+      </p>
+<p>
+        In order to create a lazy function, we need to implement a model of the FunctionEval
+        concept. For a function that takes <tt class="computeroutput"><span class="identifier">N</span></tt>
+        arguments, a model of FunctionEval must provide:
+      </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+          An <tt class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></tt>
+          that implements that takes <tt class="computeroutput"><span class="identifier">N</span></tt>
+          arguments, and implements the function logic.
+        </li>
+<li>
+          A nested metafunction <tt class="computeroutput"><span class="identifier">result</span><span class="special"><</span><span class="identifier">A1</span><span class="special">,</span> <span class="special">...</span> <span class="identifier">AN</span><span class="special">></span></tt>
+          that takes the types of the <tt class="computeroutput"><span class="identifier">N</span></tt>
+          arguments to the function and returns the result type of the function.
+          (There is a special case for function objects that accept no arguments.
+          Such nullary functors are only required to define a typedef <tt class="computeroutput"><span class="identifier">result_type</span></tt> that reflects the return
+          type of its <tt class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></tt>).
+        </li>
+</ul></div>
+<p>
+        For example, the following type implements the FunctionEval concept, in order
+        to provide a lazy factorial function:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">factorial_impl</span>
+<span class="special">{</span>
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Arg</span><span class="special">></span>
+    <span class="keyword">struct</span> <span class="identifier">result</span>
+    <span class="special">{</span>
+        <span class="keyword">typedef</span> <span class="identifier">Arg</span> <span class="identifier">type</span><span class="special">;</span>
+    <span class="special">};</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Arg</span><span class="special">></span>
+    <span class="identifier">Arg</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Arg</span> <span class="identifier">n</span><span class="special">)</span> <span class="keyword">const</span>
+    <span class="special">{</span>
+        <span class="keyword">return</span> <span class="special">(</span><span class="identifier">n</span> <span class="special"><=</span> <span class="number">0</span><span class="special">)</span> <span class="special">?</span> <span class="number">1</span> <span class="special">:</span> <span class="identifier">n</span> <span class="special">*</span> <span class="keyword">this</span><span class="special">-></span><span class="keyword">operator</span><span class="special">()(</span><span class="identifier">n</span><span class="special">-</span><span class="number">1</span><span class="special">);</span>
+    <span class="special">}</span>
+<span class="special">};</span>
+</pre>
+<p>
+        (See factorial.cpp)
+      </p>
+<p>
+        Having implemented the <tt class="computeroutput"><span class="identifier">factorial_impl</span></tt>
+        type, we can declare and instantiate a lazy <tt class="computeroutput"><span class="identifier">factorial</span></tt>
+        function this way:
+      </p>
+<pre class="programlisting">
+<span class="identifier">function</span><span class="special"><</span><span class="identifier">factorial_impl</span><span class="special">></span> <span class="identifier">factorial</span><span class="special">;</span>
+</pre>
+<p>
+        Invoking a lazy function such as <tt class="computeroutput"><span class="identifier">factorial</span></tt>
+        does not immediately execute the function object <tt class="computeroutput"><span class="identifier">factorial_impl</span></tt>.
+        Instead, an actor object is created
+        and returned to the caller. Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">factorial</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">)</span>
+</pre>
+<p>
+        does nothing more than return an actor. A second function call will invoke
+        the actual factorial function. Example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">4</span><span class="special">;</span>
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">factorial</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">)(</span><span class="identifier">i</span><span class="special">);</span>
+</pre>
+<p>
+        will print out "24".
+      </p>
+<p>
+        Take note that in certain cases (e.g. for function objects with state), an
+        instance of the model of FunctionEval may be passed on to the constructor.
+        Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">function</span><span class="special"><</span><span class="identifier">factorial_impl</span><span class="special">></span> <span class="identifier">factorial</span><span class="special">(</span><span class="identifier">ftor</span><span class="special">);</span>
+</pre>
+<p>
+        where ftor is an instance of factorial_impl (this is not necessary in this
+        case as <tt class="computeroutput"><span class="identifier">factorial_impl</span></tt> does
+        not require any state).
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/alert.png" alt="alert"></span> Take care though when using function objects with
+              state because they are often copied repeatedly, and state may change
+              in one of the copies, rather than the original.</td></tr></tbody>
+</table></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.composite.operator"></a>Operator</h3></div></div></div>
+<p>
+        This facility provides a mechanism for lazily evaluating operators. Syntactically,
+        a lazy operator looks and feels like an ordinary C/C++ infix, prefix or postfix
+        operator. The operator application looks the same. However, unlike ordinary
+        operators, the actual operator execution is deferred. Samples:
+      </p>
+<pre class="programlisting">
+<span class="identifier">arg1</span> <span class="special">+</span> <span class="identifier">arg2</span>
+<span class="number">1</span> <span class="special">+</span> <span class="identifier">arg1</span> <span class="special">*</span> <span class="identifier">arg2</span>
+<span class="number">1</span> <span class="special">/</span> <span class="special">-</span><span class="identifier">arg1</span>
+<span class="identifier">arg1</span> <span class="special"><</span> <span class="number">150</span>
+</pre>
+<p>
+        We have seen the lazy operators in action (see <a href="starter_kit.html" title="Starter Kit">Quick
+        Start</a>). Let's go back and examine them a little bit further:
+      </p>
+<pre class="programlisting">
+<span class="identifier">find_if</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">)</span>
+</pre>
+<p>
+        Through operator overloading, the expression <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span></tt> actually
+        generates an actor. This actor object is passed on to STL's <tt class="computeroutput"><span class="identifier">find_if</span></tt> function. From the viewpoint of
+        STL, the composite is simply a function object expecting a single argument
+        of the containers value_type. For each element in <tt class="computeroutput"><span class="identifier">c</span></tt>,
+        the element is passed on as an argument <tt class="computeroutput"><span class="identifier">arg1</span></tt>
+        to the actor (function object). The actor checks if this is an odd value
+        based on the expression <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span></tt> where
+        arg1 is replaced by the container's element.
+      </p>
+<p>
+        Like lazy functions (see function),
+        lazy operators are not immediately executed when invoked. Instead, an actor
+        (see actors) object is created and
+        returned to the caller. Example:
+      </p>
+<pre class="programlisting">
+<span class="special">(</span><span class="identifier">arg1</span> <span class="special">+</span> <span class="identifier">arg2</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">arg3</span>
+</pre>
+<p>
+        does nothing more than return an actor. A second function call will evaluate
+        the actual operators. Example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">4</span><span class="special">,</span> <span class="identifier">j</span> <span class="special">=</span> <span class="number">5</span><span class="special">,</span> <span class="identifier">k</span> <span class="special">=</span> <span class="number">6</span><span class="special">;</span>
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="special">((</span><span class="identifier">arg1</span> <span class="special">+</span> <span class="identifier">arg2</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">arg3</span><span class="special">)(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">j</span><span class="special">,</span> <span class="identifier">k</span><span class="special">);</span>
+</pre>
+<p>
+        will print out "54".
+      </p>
+<p>
+        Operator expressions are lazily evaluated following four simple rules:
+      </p>
+<div class="orderedlist"><ol type="1">
+<li>
+          A binary operator, except <tt class="computeroutput"><span class="special">->*</span></tt>
+          will be lazily evaluated when <span class="emphasis"><em>at least</em></span> one of its
+          operands is an actor object (see actors).
+        </li>
+<li>
+          Unary operators are lazily evaluted if their argument is an actor object.
+        </li>
+<li>
+          Operator <tt class="computeroutput"><span class="special">->*</span></tt> is lazily
+          evaluted if the left hand argument is an actor object.
+        </li>
+<li>
+          The result of a lazy operator is an actor object that can in turn allow
+          the applications of rules 1 and 2.
+        </li>
+</ol></div>
+<p>
+        For example, to check the following expression is lazily evaluated:
+      </p>
+<pre class="programlisting">
+<span class="special">-(</span><span class="identifier">arg1</span> <span class="special">+</span> <span class="number">3</span> <span class="special">+</span> <span class="number">6</span><span class="special">)</span>
+</pre>
+<div class="orderedlist"><ol type="1">
+<li>
+          Following rule 1, <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">+</span> <span class="number">3</span></tt>
+          is lazily evaluated since <tt class="computeroutput"><span class="identifier">arg1</span></tt>
+          is an actor (see primitives).
+        </li>
+<li>
+          The result of this <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">+</span> <span class="number">3</span></tt>
+          expression is an actor object, following rule 4.
+        </li>
+<li>
+          Continuing, <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">+</span> <span class="number">3</span> <span class="special">+</span> <span class="number">6</span></tt>
+          is again lazily evaluated. Rule 2.
+        </li>
+<li>
+          By rule 4 again, the result of <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">+</span> <span class="number">3</span> <span class="special">+</span> <span class="number">6</span></tt>
+          is an actor object.
+        </li>
+<li>
+          As <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">+</span> <span class="number">3</span> <span class="special">+</span> <span class="number">6</span></tt> is an actor, <tt class="computeroutput"><span class="special">-(</span><span class="identifier">arg1</span> <span class="special">+</span> <span class="number">3</span> <span class="special">+</span> <span class="number">6</span><span class="special">)</span></tt> is lazily
+          evaluated. Rule 2.
+        </li>
+</ol></div>
+<p>
+        Lazy-operator application is highly contagious. In most cases, a single
+        <tt class="computeroutput"><span class="identifier">argN</span></tt> actor infects all its
+        immediate neighbors within a group (first level or parenthesized expression).
+      </p>
+<p>
+        Note that at least one operand of any operator must be a valid actor for
+        lazy evaluation to take effect. To force lazy evaluation of an ordinary expression,
+        we can use <tt class="computeroutput"><span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></tt>, <tt class="computeroutput"><span class="identifier">val</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></tt> or <tt class="computeroutput"><span class="identifier">cref</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></tt>
+        to transform an operand into a valid actor object (see primitives.
+        For example:
+      </p>
+<pre class="programlisting">
+<span class="number">1</span> <span class="special"><<</span> <span class="number">3</span><span class="special">;</span>      <span class="comment">// Immediately evaluated
+</span><span class="identifier">val</span><span class="special">(</span><span class="number">1</span><span class="special">)</span> <span class="special"><<</span> <span class="number">3</span><span class="special">;</span> <span class="comment">// Lazily evaluated
+</span></pre>
+<a name="phoenix.composite.operator.supported_operators"></a><h2>
+<a name="id455378"></a>
+        Supported operators
+      </h2>
+<a name="phoenix.composite.operator.unary_operators"></a><h3>
+<a name="id455393"></a>
+        Unary operators
+      </h3>
+<pre class="programlisting">
+<span class="identifier">prefix</span><span class="special">:</span>   <span class="special">~,</span> <span class="special">!,</span> <span class="special">-,</span> <span class="special">+,</span> <span class="special">++,</span> <span class="special">--,</span> <span class="special">&</span> <span class="special">(</span><span class="identifier">reference</span><span class="special">),</span> <span class="special">*</span> <span class="special">(</span><span class="identifier">dereference</span><span class="special">)</span>
+<span class="identifier">postfix</span><span class="special">:</span>  <span class="special">++,</span> <span class="special">--</span>
+</pre>
+<a name="phoenix.composite.operator.binary_operators"></a><h3>
+<a name="id455528"></a>
+        Binary operators
+      </h3>
+<pre class="programlisting">
+<span class="special">=,</span> <span class="special">[],</span> <span class="special">+=,</span> <span class="special">-=,</span> <span class="special">*=,</span> <span class="special">/=,</span> <span class="special">%=,</span> <span class="special">&=,</span> <span class="special">|=,</span> <span class="special">^=,</span> <span class="special"><<=,</span> <span class="special">>>=</span>
+<span class="special">+,</span> <span class="special">-,</span> <span class="special">*,</span> <span class="special">/,</span> <span class="special">%,</span> <span class="special">&,</span> <span class="special">|,</span> <span class="special">^,</span> <span class="special"><<,</span> <span class="special">>></span>
+<span class="special">==,</span> <span class="special">!=,</span> <span class="special"><,</span> <span class="special">>,</span> <span class="special"><=,</span> <span class="special">>=</span>
+<span class="special">&&,</span> <span class="special">||,</span> <span class="special">->*</span>
+</pre>
+<a name="phoenix.composite.operator.ternary_operator"></a><h3>
+<a name="id455740"></a>
+        Ternary operator
+      </h3>
+<pre class="programlisting">
+<span class="identifier">if_else</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span>
+</pre>
+<p>
+        The ternary operator deserves special mention. Since C++ does not allow us
+        to overload the conditional expression: <tt class="computeroutput"><span class="identifier">c</span> <span class="special">?</span> <span class="identifier">a</span> <span class="special">:</span> <span class="identifier">b</span></tt>,
+        the if_else pseudo function is provided for this purpose. The behavior is
+        identical, albeit in a lazy manner.
+      </p>
+<a name="phoenix.composite.operator.member_pointer_operator"></a><h3>
+<a name="id455848"></a>
+        Member pointer operator
+      </h3>
+<pre class="programlisting">
+<span class="identifier">a</span><span class="special">->*</span><span class="identifier">member_object_pointer</span>
+<span class="identifier">a</span><span class="special">->*</span><span class="identifier">member_function_pointer</span>
+</pre>
+<p>
+        The left hand side of the member pointer operator must be an actor returning
+        a pointer type. The right hand side of the member pointer operator may be
+        either a pointer to member object or pointer to member function.
+      </p>
+<p>
+        If the right hand side is a member object pointer, the result is an actor
+        which, when evaluated, returns a reference to that member. For example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">A</span>
+<span class="special">{</span>
+    <span class="keyword">int</span> <span class="identifier">member</span><span class="special">;</span>
+<span class="special">};</span>
+
+<span class="identifier">A</span><span class="special">*</span> <span class="identifier">a</span> <span class="special">=</span> <span class="keyword">new</span> <span class="identifier">A</span><span class="special">;</span>
+<span class="special">...</span>
+
+<span class="special">(</span><span class="identifier">arg1</span><span class="special">->*&</span><span class="identifier">A</span><span class="special">::</span><span class="identifier">member</span><span class="special">)(</span><span class="identifier">a</span><span class="special">);</span> <span class="comment">// returns member a->member
+</span></pre>
+<p>
+        If the right hand side is a member function pointer, the result is an actor
+        which, when invoked, calls the specified member function. For example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">A</span>
+<span class="special">{</span>
+    <span class="keyword">int</span> <span class="identifier">func</span><span class="special">(</span><span class="keyword">int</span><span class="special">);</span>
+<span class="special">};</span>
+
+<span class="identifier">A</span><span class="special">*</span> <span class="identifier">a</span> <span class="special">=</span> <span class="keyword">new</span> <span class="identifier">A</span><span class="special">;</span>
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">0</span><span class="special">;</span>
+
+<span class="special">(</span><span class="identifier">arg1</span><span class="special">->*&</span><span class="identifier">A</span><span class="special">::</span><span class="identifier">func</span><span class="special">)(</span><span class="identifier">arg2</span><span class="special">)(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">i</span><span class="special">);</span> <span class="comment">// returns a->func(i)
+</span></pre>
+<div class="informaltable">
+<h4>
+<a name="id456264"></a>
+          <span class="table-title">Include Files</span>
+        </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Operators</th>
+<th>File</th>
+</tr></thead>
+<tbody>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">-</span></tt>, <tt class="computeroutput"><span class="special">+</span></tt>, <tt class="computeroutput"><span class="special">++</span></tt>,
+              <tt class="computeroutput"><span class="special">--</span></tt>, <tt class="computeroutput"><span class="special">+=</span></tt>,
+              <tt class="computeroutput"><span class="special">-=</span></tt>, <tt class="computeroutput"><span class="special">*=</span></tt>,
+              <tt class="computeroutput"><span class="special">/=</span></tt>, <tt class="computeroutput"><span class="special">%=</span></tt>,
+              <tt class="computeroutput"><span class="special">*</span></tt>, <tt class="computeroutput"><span class="special">/</span></tt>,
+              <tt class="computeroutput"><span class="special">%</span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">/</span><span class="identifier">arithmetic</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">&=</span></tt>, <tt class="computeroutput"><span class="special">|=</span></tt>, <tt class="computeroutput"><span class="special">^=</span></tt>,
+              <tt class="computeroutput"><span class="special"><<=</span></tt>, <tt class="computeroutput"><span class="special">>>=</span></tt>, <tt class="computeroutput"><span class="special">&</span></tt>,
+              <tt class="computeroutput"><span class="special">|</span></tt>, <tt class="computeroutput"><span class="special">^</span></tt>,
+              <tt class="computeroutput"><span class="special"><<</span></tt>, <tt class="computeroutput"><span class="special">>></span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">/</span><span class="identifier">bitwise</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">==</span></tt>, <tt class="computeroutput"><span class="special">!=</span></tt>, <tt class="computeroutput"><span class="special"><</span></tt>,
+              <tt class="computeroutput"><span class="special"><=</span></tt>, <tt class="computeroutput"><span class="special">></span></tt>,
+              <tt class="computeroutput"><span class="special">>=</span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">/</span><span class="identifier">comparison</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special"><<</span></tt>, <tt class="computeroutput"><span class="special">>></span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">/</span><span class="identifier">io</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">!</span></tt>, &&,
+              <tt class="computeroutput"><span class="special">||</span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">/</span><span class="identifier">logical</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">&</span><span class="identifier">x</span></tt>,
+              <tt class="computeroutput"><span class="special">*</span><span class="identifier">p</span></tt>,
+              <tt class="computeroutput"><span class="special">=</span></tt>, <tt class="computeroutput"><span class="special">[]</span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">/</span><span class="identifier">self</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">if_else</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">/</span><span class="identifier">if_else</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="special">->*</span></tt></td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">/</span><span class="identifier">member</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.composite.statement"></a>Statement</h3></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">Block Statement</span></dt>
+<dt><span class="section">if_ Statement</span></dt>
+<dt><span class="section">ifelse statement</span></dt>
+<dt><span class="section">switch_ statement</span></dt>
+<dt><span class="section">while_ Statement</span></dt>
+<dt><span class="section">dowhile Statement</span></dt>
+<dt><span class="section">for_ Statement</span></dt>
+<dt><span class="section">try_ catch_ Statement</span></dt>
+<dt><span class="section">throw_</span></dt>
+</dl></div>
+<p>
+        <span class="bold"><b><span class="emphasis"><em>Lazy statements...</em></span></b></span>
+      </p>
+<p>
+        The primitives and composite building blocks presented so far are sufficiently
+        powerful to construct quite elaborate structures. We have presented lazy-
+        functions and lazy-operators. How about lazy-statements? First, an appetizer:
+      </p>
+<p>
+        Print all odd-numbered contents of an STL container using <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span></tt>
+        (all_odds.cpp):
+      </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span>
+    <span class="identifier">if_</span><span class="special">(</span><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">)</span>
+    <span class="special">[</span>
+        <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span> <span class="special"><<</span> <span class="char">' '</span>
+    <span class="special">]</span>
+<span class="special">);</span>
+</pre>
+<p>
+        Huh? Is that valid C++? Read on...
+      </p>
+<p>
+        Yes, it is valid C++. The sample code above is as close as you can get to
+        the syntax of C++. This stylized C++ syntax differs from actual C++ code.
+        First, the <tt class="computeroutput"><span class="keyword">if</span></tt> has a trailing
+        underscore. Second, the block uses square brackets instead of the familiar
+        curly braces {}.
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>C++ in C++?</b></span><br>
+              <br> In as much as Spirit
+              attempts to mimic EBNF in C++, Phoenix attempts to mimic C++ in C++!!!
+              </td></tr></tbody>
+</table></div>
+<p>
+        Here are more examples with annotations. The code almost speaks for itself.
+      </p>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.block_statement"></a>Block Statement</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="identifier">sequence</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          Syntax:
+        </p>
+<pre class="programlisting">
+<span class="identifier">statement</span><span class="special">,</span>
+<span class="identifier">statement</span><span class="special">,</span>
+<span class="special">....</span>
+<span class="identifier">statement</span>
+</pre>
+<p>
+          Basically, these are comma separated statements. Take note that unlike
+          the C/C++ semicolon, the comma is a separator put <span class="bold"><b>in-between</b></span>
+          statements. This is like Pascal's semicolon separator, rather than C/C++'s
+          semicolon terminator. For example:
+        </p>
+<pre class="programlisting">
+<span class="identifier">statement</span><span class="special">,</span>
+<span class="identifier">statement</span><span class="special">,</span>
+<span class="identifier">statement</span><span class="special">,</span> <span class="comment">// ERROR!
+</span></pre>
+<p>
+          Is an error. The last statement should not have a comma. Block statements
+          can be grouped using the parentheses. Again, the last statement in a group
+          should not have a trailing comma.
+        </p>
+<pre class="programlisting">
+<span class="identifier">statement</span><span class="special">,</span>
+<span class="identifier">statement</span><span class="special">,</span>
+<span class="special">(</span>
+    <span class="identifier">statement</span><span class="special">,</span>
+    <span class="identifier">statement</span>
+<span class="special">),</span>
+<span class="identifier">statement</span>
+</pre>
+<p>
+          Outside the square brackets, block statements should be grouped. For example:
+        </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span>
+    <span class="special">(</span>
+        <span class="identifier">do_this</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">),</span>
+        <span class="identifier">do_that</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">)</span>
+    <span class="special">)</span>
+<span class="special">);</span>
+</pre>
+<p>
+          Wrapping a comma operator chain around a parentheses pair blocks the interpretation
+          as an argument separator. The reason for the exception for the square bracket
+          operator is that the operator always takes exactly one argument, so it
+          "transforms" any attempt at multiple arguments with a comma operator
+          chain (and spits out an error for zero arguments).
+        </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.if__statement"></a>if_ Statement</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="keyword">if</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          We have seen the <tt class="computeroutput"><span class="identifier">if_</span></tt> statement.
+          The syntax is:
+        </p>
+<pre class="programlisting">
+<span class="identifier">if_</span><span class="special">(</span><span class="identifier">conditional_expression</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statements</span>
+<span class="special">]</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.if_else__statement"></a>if<span class="underline">else</span> statement</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="keyword">if</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          The syntax is
+        </p>
+<pre class="programlisting">
+<span class="identifier">if_</span><span class="special">(</span><span class="identifier">conditional_expression</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statements</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">else_</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statements</span>
+<span class="special">]</span>
+</pre>
+<p>
+          Take note that <tt class="computeroutput"><span class="keyword">else</span></tt> has a
+          leading dot and a trailing underscore: <tt class="computeroutput"><span class="special">.</span><span class="identifier">else_</span></tt>
+        </p>
+<p>
+          Example: This code prints out all the elements and appends <tt class="computeroutput"><span class="string">" > 5"</span></tt>, <tt class="computeroutput"><span class="string">"
+          == 5"</span></tt> or <tt class="computeroutput"><span class="string">" < 5"</span></tt>
+          depending on the element's actual value:
+        </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span>
+    <span class="identifier">if_</span><span class="special">(</span><span class="identifier">arg1</span> <span class="special">></span> <span class="number">5</span><span class="special">)</span>
+    <span class="special">[</span>
+        <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span> <span class="special"><<</span> <span class="string">" > 5\n"</span>
+    <span class="special">]</span>
+    <span class="special">.</span><span class="identifier">else_</span>
+    <span class="special">[</span>
+        <span class="identifier">if_</span><span class="special">(</span><span class="identifier">arg1</span> <span class="special">==</span> <span class="number">5</span><span class="special">)</span>
+        <span class="special">[</span>
+            <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span> <span class="special"><<</span> <span class="string">" == 5\n"</span>
+        <span class="special">]</span>
+        <span class="special">.</span><span class="identifier">else_</span>
+        <span class="special">[</span>
+            <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span> <span class="special"><<</span> <span class="string">" < 5\n"</span>
+        <span class="special">]</span>
+    <span class="special">]</span>
+<span class="special">);</span>
+</pre>
+<p>
+          Notice how the <tt class="computeroutput"><span class="identifier">if_else_</span></tt>
+          statement is nested.
+        </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.switch__statement"></a>switch_ statement</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="keyword">switch</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          The syntax is:
+        </p>
+<pre class="programlisting">
+<span class="identifier">switch_</span><span class="special">(</span><span class="identifier">integral_expression</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">case_</span><span class="special"><</span><span class="identifier">integral_value</span><span class="special">>(</span><span class="identifier">sequenced_statements</span><span class="special">),</span>
+    <span class="special">...</span>
+    <span class="identifier">default_</span><span class="special"><</span><span class="identifier">integral_value</span><span class="special">>(</span><span class="identifier">sequenced_statements</span><span class="special">)</span>
+<span class="special">]</span>
+</pre>
+<p>
+          A comma separated list of cases, and an optional default can be provided.
+          Note unlike a normal switch statement, cases do not fall through.
+        </p>
+<p>
+          Example: This code prints out <tt class="computeroutput"><span class="string">"one"</span></tt>,
+          <tt class="computeroutput"><span class="string">"two"</span></tt> or <tt class="computeroutput"><span class="string">"other value"</span></tt> depending on the
+          element's actual value:
+        </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span>
+    <span class="identifier">switch_</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">)</span>
+    <span class="special">[</span>
+        <span class="identifier">case_</span><span class="special"><</span><span class="number">1</span><span class="special">>(</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"one"</span><span class="special">)</span> <span class="special"><<</span> <span class="char">'\n'</span><span class="special">),</span>
+        <span class="identifier">case_</span><span class="special"><</span><span class="number">2</span><span class="special">>(</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"two"</span><span class="special">)</span> <span class="special"><<</span> <span class="char">'\n'</span><span class="special">),</span>
+        <span class="identifier">default_</span><span class="special">(</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"other value"</span><span class="special">)</span> <span class="special"><<</span> <span class="char">'\n'</span><span class="special">)</span>
+    <span class="special">]</span>
+<span class="special">);</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.while__statement"></a>while_ Statement</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="keyword">while</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          The syntax is:
+        </p>
+<pre class="programlisting">
+<span class="identifier">while_</span><span class="special">(</span><span class="identifier">conditional_expression</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statements</span>
+<span class="special">]</span>
+</pre>
+<p>
+          Example: This code decrements each element until it reaches zero and prints
+          out the number at each step. A newline terminates the printout of each
+          value.
+        </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span>
+    <span class="special">(</span>
+        <span class="identifier">while_</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">--)</span>
+        <span class="special">[</span>
+            <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span> <span class="special"><<</span> <span class="string">", "</span>
+        <span class="special">],</span>
+        <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"\n"</span><span class="special">)</span>
+    <span class="special">)</span>
+<span class="special">);</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.do_while__statement"></a>do<span class="underline">while</span> Statement</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="identifier">do_while</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          The syntax is:
+        </p>
+<pre class="programlisting">
+<span class="identifier">do_</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statements</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">while_</span><span class="special">(</span><span class="identifier">conditional_expression</span><span class="special">)</span>
+</pre>
+<p>
+          Again, take note that <tt class="computeroutput"><span class="keyword">while</span></tt>
+          has a leading dot and a trailing underscore: <tt class="computeroutput"><span class="special">.</span><span class="identifier">while_</span></tt>
+        </p>
+<p>
+          Example: This code is almost the same as the previous example above with
+          a slight twist in logic.
+        </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span>
+    <span class="special">(</span>
+        <span class="identifier">do_</span>
+        <span class="special">[</span>
+            <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span> <span class="special"><<</span> <span class="string">", "</span>
+        <span class="special">]</span>
+        <span class="special">.</span><span class="identifier">while_</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">--),</span>
+        <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"\n"</span><span class="special">)</span>
+    <span class="special">)</span>
+<span class="special">);</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.for__statement"></a>for_ Statement</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="keyword">for</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          The syntax is:
+        </p>
+<pre class="programlisting">
+<span class="identifier">for_</span><span class="special">(</span><span class="identifier">init_statement</span><span class="special">,</span> <span class="identifier">conditional_expression</span><span class="special">,</span> <span class="identifier">step_statement</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statements</span>
+<span class="special">]</span>
+</pre>
+<p>
+          It is again very similar to the C++ for statement. Take note that the init_statement,
+          conditional_expression and step_statement are separated by the comma instead
+          of the semi-colon and each must be present (i.e. <tt class="computeroutput"><span class="identifier">for_</span><span class="special">(,,)</span></tt> is invalid). This is a case where the
+          nothing actor can be
+          useful.
+        </p>
+<p>
+          Example: This code prints each element N times where N is the element's
+          value. A newline terminates the printout of each value.
+        </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">iii</span><span class="special">;</span>
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span>
+    <span class="special">(</span>
+        <span class="identifier">for_</span><span class="special">(</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">iii</span><span class="special">)</span> <span class="special">=</span> <span class="number">0</span><span class="special">,</span> <span class="identifier">ref</span><span class="special">(</span><span class="identifier">iii</span><span class="special">)</span> <span class="special"><</span> <span class="identifier">arg1</span><span class="special">,</span> <span class="special">++</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">iii</span><span class="special">))</span>
+        <span class="special">[</span>
+            <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span> <span class="special"><<</span> <span class="string">", "</span>
+        <span class="special">],</span>
+        <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"\n"</span><span class="special">)</span>
+    <span class="special">)</span>
+<span class="special">);</span>
+</pre>
+<p>
+          As before, all these are lazily evaluated. The result of such statements
+          are in fact composites that are passed on to STL's for_each function. In
+          the viewpoint of <tt class="computeroutput"><span class="identifier">for_each</span></tt>,
+          what was passed is just a functor, no more, no less.
+        </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> Unlike lazy functions and lazy operators, lazy
+                statements always return void.</td></tr></tbody>
+</table></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.try__catch__statement"></a>try_ catch_ Statement</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="identifier">try_catch</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          The syntax is:
+        </p>
+<pre class="programlisting">
+<span class="identifier">try_</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statements</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">catch_</span><span class="special"><</span><span class="identifier">exception_type</span><span class="special">>()</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statements</span>
+<span class="special">]</span>
+<span class="special">...</span>
+<span class="special">.</span><span class="identifier">catch_all</span>
+<span class="special">[</span>
+    <span class="identifier">sequenced_statement</span>
+<span class="special">]</span>
+</pre>
+<p>
+          Note the usual underscore after try and catch, and the extra parentheses
+          required after the catch.
+        </p>
+<p>
+          Example: The following code calls the (lazy) function <tt class="computeroutput"><span class="identifier">f</span></tt>
+          for each element, and prints messages about different exception types it
+          catches.
+        </p>
+<pre class="programlisting">
+<span class="identifier">try_</span>
+<span class="special">[</span>
+    <span class="identifier">f</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">)</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">catch_</span><span class="special"><</span><span class="identifier">runtime_error</span><span class="special">>()</span>
+<span class="special">[</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"caught runtime error or derived\n"</span><span class="special">)</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">catch_</span><span class="special"><</span><span class="identifier">exception</span><span class="special">>()</span>
+<span class="special">[</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"caught exception or derived\n"</span><span class="special">)</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">catch_all</span>
+<span class="special">[</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"caught some other type of exception\n"</span><span class="special">)</span>
+<span class="special">]</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.composite.statement.throw_"></a>throw_</h4></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">/</span><span class="keyword">throw</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+          As a natural companion to the try/catch support, the statement module provides
+          lazy throwing and rethrowing of exceptions.
+        </p>
+<p>
+          The syntax to throw an exception is:
+        </p>
+<pre class="programlisting">
+<span class="identifier">throw_</span><span class="special">(</span><span class="identifier">exception_expression</span><span class="special">)</span>
+</pre>
+<p>
+          The syntax to rethrow an exception is:
+        </p>
+<pre class="programlisting">
+<span class="identifier">throw_</span><span class="special">()</span>
+</pre>
+<p>
+          Example: This code extends the try/catch example, rethrowing exceptions
+          derived from runtime_error or exception, and translating other exception
+          types to runtime_errors.
+        </p>
+<pre class="programlisting">
+<span class="identifier">try_</span>
+<span class="special">[</span>
+    <span class="identifier">f</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">)</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">catch_</span><span class="special"><</span><span class="identifier">runtime_error</span><span class="special">>()</span>
+<span class="special">[</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"caught runtime error or derived\n"</span><span class="special">),</span>
+    <span class="identifier">throw_</span><span class="special">()</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">catch_</span><span class="special"><</span><span class="identifier">exception</span><span class="special">>()</span>
+<span class="special">[</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"caught exception or derived\n"</span><span class="special">),</span>
+    <span class="identifier">throw_</span><span class="special">()</span>
+<span class="special">]</span>
+<span class="special">.</span><span class="identifier">catch_all</span>
+<span class="special">[</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"caught some other type of exception\n"</span><span class="special">),</span>
+    <span class="identifier">throw_</span><span class="special">(</span><span class="identifier">runtime_error</span><span class="special">(</span><span class="string">"translated exception"</span><span class="special">))</span>
+<span class="special">]</span>
+</pre>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.composite.object"></a>Object</h3></div></div></div>
+<p>
+        The Object module deals with object construction, destruction and conversion.
+        The module provides <span class="emphasis"><em>"lazy"</em></span> versions of C++'s
+        object constructor, <tt class="computeroutput"><span class="keyword">new</span></tt>, <tt class="computeroutput"><span class="keyword">delete</span></tt>, <tt class="computeroutput"><span class="keyword">static_cast</span></tt>,
+        <tt class="computeroutput"><span class="keyword">dynamic_cast</span></tt>, <tt class="computeroutput"><span class="keyword">const_cast</span></tt> and <tt class="computeroutput"><span class="keyword">reinterpret_cast</span></tt>.
+      </p>
+<a name="phoenix.composite.object.construction"></a><h2>
+<a name="id461627"></a>
+        Construction
+      </h2>
+<p>
+        <span class="bold"><b><span class="emphasis"><em>Lazy constructors...</em></span></b></span>
+      </p>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">object</span><span class="special">/</span><span class="identifier">construct</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Lazily construct an object from an arbitrary set of arguments:
+      </p>
+<pre class="programlisting">
+<span class="identifier">construct</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">ctor_arg1</span><span class="special">,</span> <span class="identifier">ctor_arg2</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">ctor_argN</span><span class="special">);</span>
+</pre>
+<p>
+        where the given parameters are the parameters to the contructor of the object
+        of type T (This implies, that type T is expected to have a constructor with
+        a corresponding set of parameter types.).
+      </p>
+<p>
+        Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">construct</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)</span>
+</pre>
+<p>
+        Constructs a <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></tt> from <tt class="computeroutput"><span class="identifier">arg1</span></tt>
+        and <tt class="computeroutput"><span class="identifier">arg2</span></tt>.
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> The maximum number of actual parameters is limited
+              by the preprocessor constant PHOENIX_COMPOSITE_LIMIT. Note though,
+              that this limit should not be greater than PHOENIX_LIMIT. By default,
+              <tt class="computeroutput"><span class="identifier">PHOENIX_COMPOSITE_LIMIT</span></tt>
+              is set to <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt>
+              (See Actors).</td></tr></tbody>
+</table></div>
+<a name="phoenix.composite.object.new"></a><h2>
+<a name="id461989"></a>
+        New
+      </h2>
+<p>
+        <span class="bold"><b><span class="emphasis"><em>Lazy new...</em></span></b></span>
+      </p>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">object</span><span class="special">/</span><span class="keyword">new</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Lazily construct an object, on the heap, from an arbitrary set of arguments:
+      </p>
+<pre class="programlisting">
+<span class="identifier">new_</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">ctor_arg1</span><span class="special">,</span> <span class="identifier">ctor_arg2</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">ctor_argN</span><span class="special">);</span>
+</pre>
+<p>
+        where the given parameters are the parameters to the contructor of the object
+        of type T (This implies, that type T is expected to have a constructor with
+        a corresponding set of parameter types.).
+      </p>
+<p>
+        Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">new_</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)</span> <span class="comment">// note the spelling of new_ (with trailing underscore)
+</span></pre>
+<p>
+        Creates a <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span></tt> from <tt class="computeroutput"><span class="identifier">arg1</span></tt>
+        and <tt class="computeroutput"><span class="identifier">arg2</span></tt> on the heap.
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> Again, the maximum number of actual parameters
+              is limited by the preprocessor constant PHOENIX_COMPOSITE_LIMIT. See
+              the note above.</td></tr></tbody>
+</table></div>
+<a name="phoenix.composite.object.delete"></a><h2>
+<a name="id462327"></a>
+        Delete
+      </h2>
+<p>
+        <span class="bold"><b><span class="emphasis"><em>Lazy delete...</em></span></b></span>
+      </p>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">object</span><span class="special">/</span><span class="keyword">delete</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Lazily delete an object, from the heap:
+      </p>
+<pre class="programlisting">
+<span class="identifier">delete_</span><span class="special">(</span><span class="identifier">arg</span><span class="special">);</span>
+</pre>
+<p>
+        where arg is assumed to be a pointer to an object.
+      </p>
+<p>
+        Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">delete_</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>(</span><span class="identifier">arg1</span><span class="special">)</span> <span class="comment">// note the spelling of delete_ (with trailing underscore)
+</span></pre>
+<a name="phoenix.composite.object.casts"></a><h2>
+<a name="id462522"></a>
+        Casts
+      </h2>
+<p>
+        <span class="bold"><b><span class="emphasis"><em>Lazy casts...</em></span></b></span>
+      </p>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">object</span><span class="special">/</span><span class="keyword">static_cast</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">object</span><span class="special">/</span><span class="keyword">dynamic_cast</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">object</span><span class="special">/</span><span class="keyword">const_cast</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">object</span><span class="special">/</span><span class="keyword">reinterpret_cast</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        The set of lazy C++ cast template functions provide a way of lazily casting
+        an object of a certain type to another type. The syntax resembles the well
+        known C++ casts. Take note however that the lazy versions have a trailing
+        underscore.
+      </p>
+<pre class="programlisting">
+<span class="identifier">static_cast_</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">lambda_expression</span><span class="special">)</span>
+<span class="identifier">dynamic_cast_</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">lambda_expression</span><span class="special">)</span>
+<span class="identifier">const_cast_</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">lambda_expression</span><span class="special">)</span>
+<span class="identifier">reinterpret_cast_</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">lambda_expression</span><span class="special">)</span>
+</pre>
+<p>
+        Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">static_cast_</span><span class="special"><</span><span class="identifier">Base</span><span class="special">*>(&</span><span class="identifier">arg1</span><span class="special">)</span>
+</pre>
+<p>
+        Static-casts the address of <tt class="computeroutput"><span class="identifier">arg1</span></tt>
+        to a <tt class="computeroutput"><span class="identifier">Base</span><span class="special">*</span></tt>.
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.composite.scope"></a>Scope</h3></div></div></div>
+<p>
+        Up until now, the most basic ingredient is missing: creation of and access
+        to local variables in the stack. When recursion comes into play, you will
+        soon realize the need to have true local variables. It may seem that we do
+        not need this at all since an unnamed lambda function cannot call itself
+        anyway; at least not directly. With some sort of arrangement, situations
+        will arise where a lambda function becomes recursive. A typical situation
+        occurs when we store a lambda function in a Boost.Function,
+        essentially naming the unnamed lambda.
+      </p>
+<p>
+        There will also be situations where a lambda function gets passed as an argument
+        to another function. This is a more common situation. In this case, the lambda
+        function assumes a new scope; new arguments and possibly new local variables.
+      </p>
+<p>
+        This section deals with local variables and nested lambda scopes.
+      </p>
+<a name="phoenix.composite.scope.local_variables"></a><h2>
+<a name="id463114"></a>
+        Local Variables
+      </h2>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">scope</span><span class="special">/</span><span class="identifier">local_variable</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        We use an instance of:
+      </p>
+<pre class="programlisting">
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">local_variable</span><span class="special"><</span><span class="identifier">Key</span><span class="special">></span> <span class="special">></span>
+</pre>
+<p>
+        to represent a local variable. The local variable acts as an imaginary data-bin
+        where a local, stack based data will be placed. <tt class="computeroutput"><span class="identifier">Key</span></tt>
+        is an arbitrary type that is used to identify the local variable. Example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">size_key</span><span class="special">;</span>
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">local_variable</span><span class="special"><</span><span class="identifier">size_key</span><span class="special">></span> <span class="special">></span> <span class="identifier">size</span><span class="special">;</span>
+</pre>
+<a name="phoenix.composite.scope.predefined_local_variables"></a><h2>
+<a name="id463348"></a>
+        Predefined Local Variables
+      </h2>
+<p>
+        There are a few predefined instances of <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">local_variable</span><span class="special"><</span><span class="identifier">Key</span><span class="special">></span> <span class="special">></span></tt>
+        named <tt class="computeroutput"><span class="identifier">_a</span></tt>..<tt class="computeroutput"><span class="identifier">_z</span></tt>
+        that you can already use. To make use of them, simply use the <tt class="computeroutput"><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">local_names</span></tt>:
+      </p>
+<pre class="programlisting">
+<span class="keyword">using</span> <span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">phoenix</span><span class="special">::</span><span class="identifier">local_names</span><span class="special">;</span>
+</pre>
+<a name="phoenix.composite.scope.let"></a><h2>
+<a name="id463515"></a>
+        let
+      </h2>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">scope</span><span class="special">/</span><span class="identifier">let</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        You declare local variables using the syntax:
+      </p>
+<pre class="programlisting">
+<span class="identifier">let</span><span class="special">(</span><span class="identifier">local</span><span class="special">-</span><span class="identifier">declarations</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">let</span><span class="special">-</span><span class="identifier">body</span>
+<span class="special">]</span>
+</pre>
+<p>
+        <tt class="computeroutput"><span class="identifier">let</span></tt> allows 1..N local variable
+        declarations (where N == <tt class="computeroutput"><span class="identifier">PHOENIX_LOCAL_LIMIT</span></tt>).
+        Each declaration follows the form:
+      </p>
+<pre class="programlisting">
+<span class="identifier">local</span><span class="special">-</span><span class="identifier">id</span> <span class="special">=</span> <span class="identifier">lambda</span><span class="special">-</span><span class="identifier">expression</span>
+</pre>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> You can set <tt class="computeroutput"><span class="identifier">PHOENIX_LOCAL_LIMIT</span></tt>,
+              the predefined maximum local variable declarations in a let expression.
+              By default, <tt class="computeroutput"><span class="identifier">PHOENIX_LOCAL_LIMIT</span></tt>
+              is set to <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt>.</td></tr></tbody>
+</table></div>
+<p>
+        Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="number">123</span><span class="special">,</span> <span class="identifier">_b</span> <span class="special">=</span> <span class="number">456</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">_a</span> <span class="special">+</span> <span class="identifier">_b</span>
+<span class="special">]</span>
+</pre>
+<a name="phoenix.composite.scope.reference_preservation"></a><h2>
+<a name="id463919"></a>
+        Reference Preservation
+      </h2>
+<p>
+        The type of the local variable assumes the type of the lambda- expression.
+        Type deduction is reference preserving. For example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">_b</span> <span class="special">=</span> <span class="number">456</span><span class="special">)</span>
+</pre>
+<p>
+        <tt class="computeroutput"><span class="identifier">_a</span></tt> assumes the type of <tt class="computeroutput"><span class="identifier">arg1</span></tt>: a reference to an argument, while
+        <tt class="computeroutput"><span class="identifier">_b</span></tt> has type <tt class="computeroutput"><span class="keyword">int</span></tt>.
+      </p>
+<p>
+        Consider this:
+      </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>
+
+<span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="identifier">arg1</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="special">--</span><span class="identifier">_a</span> <span class="special"><<</span> <span class="char">' '</span>
+<span class="special">]</span>
+<span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
+
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>
+</pre>
+<p>
+        the output of above is : 0 0
+      </p>
+<p>
+        While with this:
+      </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>
+
+<span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="identifier">val</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">))</span>
+<span class="special">[</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="special">--</span><span class="identifier">_a</span> <span class="special"><<</span> <span class="char">' '</span>
+<span class="special">]</span>
+<span class="special">(</span><span class="identifier">i</span><span class="special">);</span>
+
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">i</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>
+</pre>
+<p>
+        the output is : 0 1
+      </p>
+<p>
+        Reference preservation is necessary because we need to have L-value access
+        to outer lambda-scopes (especially the arguments). <tt class="computeroutput"><span class="identifier">arg</span></tt>s
+        and <tt class="computeroutput"><span class="identifier">ref</span></tt>s are L-values. <tt class="computeroutput"><span class="identifier">val</span></tt>s are R-values.
+      </p>
+<a name="phoenix.composite.scope.visibility"></a><h2>
+<a name="id464447"></a>
+        Visibility
+      </h2>
+<p>
+        The scope and lifetimes of the local variables is limited within the let-body.
+        <tt class="computeroutput"><span class="identifier">let</span></tt> blocks can be nested.
+        A local variable may hide an outer local variable. For example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">let</span><span class="special">(</span><span class="identifier">_x</span> <span class="special">=</span> <span class="number">1</span><span class="special">,</span> <span class="identifier">_y</span> <span class="special">=</span> <span class="string">", World"</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="comment">// _x here is an int: 1
+</span>
+    <span class="identifier">let</span><span class="special">(</span><span class="identifier">_x</span> <span class="special">=</span> <span class="string">"Hello"</span><span class="special">)</span> <span class="comment">// hides the outer _x
+</span>    <span class="special">[</span>
+        <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">_x</span> <span class="special"><<</span> <span class="identifier">_y</span> <span class="comment">// prints "Hello, World"
+</span>    <span class="special">]</span>
+<span class="special">]</span>
+</pre>
+<p>
+        The RHS (right hand side lambda-expression) of each local-declaration cannot
+        refer to any LHS local-id. At this point, the local-ids are not in scope
+        yet; they will only be in scope in the let-body. The code below is in error:
+      </p>
+<pre class="programlisting">
+<span class="identifier">let</span><span class="special">(</span>
+    <span class="identifier">_a</span> <span class="special">=</span> <span class="number">1</span>
+  <span class="special">,</span> <span class="identifier">_b</span> <span class="special">=</span> <span class="identifier">_a</span> <span class="comment">// Error: _a is not in scope yet
+</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="comment">// _a and _b's scope starts here
+</span>    <span class="comment">/*. body .*/</span>
+<span class="special">]</span>
+</pre>
+<p>
+        However, if an outer let scope is available, this will be searched. Since
+        the scope of the RHS of a local-declaration is the outer scope enclosing
+        the let, the RHS of a local-declaration can refer to a local variable of
+        an outer scope:
+      </p>
+<pre class="programlisting">
+<span class="identifier">let</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="number">1</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">let</span><span class="special">(</span>
+        <span class="identifier">_a</span> <span class="special">=</span> <span class="number">1</span>
+      <span class="special">,</span> <span class="identifier">_b</span> <span class="special">=</span> <span class="identifier">_a</span> <span class="comment">// Ok. _a refers to the outer _a
+</span>    <span class="special">)</span>
+    <span class="special">[</span>
+        <span class="comment">/*. body .*/</span>
+    <span class="special">]</span>
+<span class="special">]</span>
+</pre>
+<a name="phoenix.composite.scope.lambda"></a><h2>
+<a name="id464895"></a>
+        lambda
+      </h2>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">scope</span><span class="special">/</span><span class="identifier">lambda</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        A lot of times, you'd want to write a lazy function that accepts one or more
+        functions (higher order functions). STL algorithms come to mind, for example.
+        Consider a lazy version of <tt class="computeroutput"><span class="identifier">stl</span><span class="special">::</span><span class="identifier">for_each</span></tt>:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">for_each_impl</span>
+<span class="special">{</span>
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">F</span><span class="special">></span>
+    <span class="keyword">struct</span> <span class="identifier">result</span>
+    <span class="special">{</span>
+        <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">type</span><span class="special">;</span>
+    <span class="special">};</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">F</span><span class="special">></span>
+    <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">C</span><span class="special">&</span> <span class="identifier">c</span><span class="special">,</span> <span class="identifier">F</span> <span class="identifier">f</span><span class="special">)</span> <span class="keyword">const</span>
+    <span class="special">{</span>
+        <span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">f</span><span class="special">);</span>
+    <span class="special">}</span>
+<span class="special">};</span>
+
+<span class="identifier">function</span><span class="special"><</span><span class="identifier">for_each_impl</span><span class="special">></span> <span class="keyword">const</span> <span class="identifier">for_each</span> <span class="special">=</span> <span class="identifier">for_each_impl</span><span class="special">();</span>
+</pre>
+<p>
+        Notice that the function accepts another function, <tt class="computeroutput"><span class="identifier">f</span></tt>
+        as an argument. The scope of this function, <tt class="computeroutput"><span class="identifier">f</span></tt>,
+        is limited within the <tt class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></tt>. When <tt class="computeroutput"><span class="identifier">f</span></tt>
+        is called inside <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span></tt>, it exists in a new scope, along
+        with new arguments and, possibly, local variables. This new scope is not
+        at all related to the outer scopes beyond the <tt class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></tt>.
+      </p>
+<p>
+        Simple syntax:
+      </p>
+<pre class="programlisting">
+<span class="identifier">lambda</span>
+<span class="special">[</span>
+    <span class="identifier">lambda</span><span class="special">-</span><span class="identifier">body</span>
+<span class="special">]</span>
+</pre>
+<p>
+        Like <tt class="computeroutput"><span class="identifier">let</span></tt>, local variables
+        may be declared, allowing 1..N local variable declarations (where N == <tt class="computeroutput"><span class="identifier">PHOENIX_LOCAL_LIMIT</span></tt>):
+      </p>
+<pre class="programlisting">
+<span class="identifier">lambda</span><span class="special">(</span><span class="identifier">local</span><span class="special">-</span><span class="identifier">declarations</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">lambda</span><span class="special">-</span><span class="identifier">body</span>
+<span class="special">]</span>
+</pre>
+<p>
+        The same restrictions apply with regard to scope and visibility. The RHS
+        (right hand side lambda-expression) of each local-declaration cannot refer
+        to any LHS local-id. The local-ids are not in scope yet; they will be in
+        scope only in the lambda-body:
+      </p>
+<pre class="programlisting">
+<span class="identifier">lambda</span><span class="special">(</span>
+    <span class="identifier">_a</span> <span class="special">=</span> <span class="number">1</span>
+  <span class="special">,</span> <span class="identifier">_b</span> <span class="special">=</span> <span class="identifier">_a</span> <span class="comment">// Error: _a is not in scope yet
+</span><span class="special">)</span>
+</pre>
+<p>
+        See <a href="composite.html#phoenix.composite.scope.visibility"><tt class="computeroutput"><span class="identifier">let</span></tt>
+        Visibility</a> above for more information.
+      </p>
+<p>
+        Example: Using our lazy <tt class="computeroutput"><span class="identifier">for_each</span></tt>
+        let's print all the elements in a container:
+      </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">lambda</span><span class="special">[</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">])</span>
+</pre>
+<p>
+        As far as the arguments are concerned (arg1..argN), the scope in which the
+        lambda-body exists is totally new. The left <tt class="computeroutput"><span class="identifier">arg1</span></tt>
+        refers to the argument passed to <tt class="computeroutput"><span class="identifier">for_each</span></tt>
+        (a container). The right <tt class="computeroutput"><span class="identifier">arg1</span></tt>
+        refers to the argument passed by <tt class="computeroutput"><span class="identifier">std</span><span class="special">::</span><span class="identifier">for_each</span></tt>
+        when we finally get to call <tt class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></tt> in our <tt class="computeroutput"><span class="identifier">for_each_impl</span></tt>
+        above (a container element).
+      </p>
+<p>
+        Yet, we may wish to get information from outer scopes. While we do not have
+        access to arguments in outer scopes, what we still have is access to local
+        variables from outer scopes. We may only be able to pass argument related
+        information from outer <tt class="computeroutput"><span class="identifier">lambda</span></tt>
+        scopes through the local variables.
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> This is a crucial difference between <tt class="computeroutput"><span class="identifier">let</span></tt> and <tt class="computeroutput"><span class="identifier">lambda</span></tt>:
+              <tt class="computeroutput"><span class="identifier">let</span></tt> does not introduce
+              new arguments; <tt class="computeroutput"><span class="identifier">lambda</span></tt>
+              does.</td></tr></tbody>
+</table></div>
+<p>
+        Another example: Using our lazy <tt class="computeroutput"><span class="identifier">for_each</span></tt>,
+        and a lazy <tt class="computeroutput"><span class="identifier">push_back</span></tt>:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">push_back_impl</span>
+<span class="special">{</span>
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
+    <span class="keyword">struct</span> <span class="identifier">result</span>
+    <span class="special">{</span>
+        <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">type</span><span class="special">;</span>
+    <span class="special">};</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">C</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
+    <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">C</span><span class="special">&</span> <span class="identifier">c</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span>
+    <span class="special">{</span>
+        <span class="identifier">c</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">x</span><span class="special">);</span>
+    <span class="special">}</span>
+<span class="special">};</span>
+
+<span class="identifier">function</span><span class="special"><</span><span class="identifier">push_back_impl</span><span class="special">></span> <span class="keyword">const</span> <span class="identifier">push_back</span> <span class="special">=</span> <span class="identifier">push_back_impl</span><span class="special">();</span>
+</pre>
+<p>
+        write a lambda expression that accepts:
+      </p>
+<div class="orderedlist"><ol type="1">
+<li>
+          a 2-dimensional container (e.g. <tt class="computeroutput"><span class="identifier">vector</span><span class="special"><</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">></span></tt>)
+        </li>
+<li>
+          a container element (e.g. <tt class="computeroutput"><span class="keyword">int</span></tt>)
+        </li>
+</ol></div>
+<p>
+        and pushes-back the element to each of the <tt class="computeroutput"><span class="identifier">vector</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span></tt>.
+      </p>
+<p>
+        Solution:
+      </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> 
+    <span class="identifier">lambda</span><span class="special">(</span><span class="identifier">_a</span> <span class="special">=</span> <span class="identifier">arg2</span><span class="special">)</span>
+    <span class="special">[</span>
+        <span class="identifier">push_back</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">_a</span><span class="special">)</span>
+    <span class="special">]</span>
+<span class="special">)</span>
+</pre>
+<p>
+        Since we do not have access to the arguments of the outer scopes beyond the
+        lambda-body, we introduce a local variable <tt class="computeroutput"><span class="identifier">_a</span></tt>
+        that captures the second outer argument: <tt class="computeroutput"><span class="identifier">arg2</span></tt>.
+        Hence: _a = arg2. This local variable is visible inside the lambda scope.
+      </p>
+<p>
+        (See lambda.cpp)
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.composite.bind"></a>Bind</h3></div></div></div>
+<p>
+        <span class="emphasis"><em>Binding</em></span> is the act of tying together a function to some
+        arguments for deferred (lazy) evaluation. Named <a href="composite.html#phoenix.composite.function" title="Function">Lazy
+        functions</a> require a bit of typing. Unlike (unnamed) lambda expressions,
+        we need to write a functor somewhere offline, detached from the call site.
+        If you wish to transform a plain function, member function or member variable
+        to a lambda expression, <tt class="computeroutput"><span class="identifier">bind</span></tt>
+        is your friend.
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> Take note that binders are monomorphic. Rather
+              than binding functions, the preferred way is to write true generic
+              and polymorphic lazy-functions.
+              However, since most of the time we are dealing with adaptation of exisiting
+              code, binders get the job done faster.</td></tr></tbody>
+</table></div>
+<p>
+        There is a set of overloaded <tt class="computeroutput"><span class="identifier">bind</span></tt>
+        template functions. Each <tt class="computeroutput"><span class="identifier">bind</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></tt>
+        function generates a suitable binder object, a composite.
+      </p>
+<a name="phoenix.composite.bind.binding_functions"></a><h2>
+<a name="id466754"></a>
+        Binding Functions
+      </h2>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">bind</span><span class="special">/</span><span class="identifier">bind_function</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Example, given a function <tt class="computeroutput"><span class="identifier">foo</span></tt>:
+      </p>
+<pre class="programlisting">
+<span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">n</span><span class="special">)</span> 
+<span class="special">{</span> 
+    <span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">n</span> <span class="special"><<</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span> 
+<span class="special">}</span>
+</pre>
+<p>
+        Here's how the function <tt class="computeroutput"><span class="identifier">foo</span></tt>
+        may be bound:
+      </p>
+<pre class="programlisting">
+<span class="identifier">bind</span><span class="special">(&</span><span class="identifier">foo</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">)</span>
+</pre>
+<p>
+        This is now a full-fledged composite
+        that can finally be evaluated by another function call invocation. A second
+        function call will invoke the actual <tt class="computeroutput"><span class="identifier">foo</span></tt>
+        function. Example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">4</span><span class="special">;</span>
+<span class="identifier">bind</span><span class="special">(&</span><span class="identifier">foo</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">)(</span><span class="identifier">i</span><span class="special">);</span>
+</pre>
+<p>
+        will print out "4".
+      </p>
+<a name="phoenix.composite.bind.binding_member_functions"></a><h2>
+<a name="id467129"></a>
+        Binding Member Functions
+      </h2>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">bind</span><span class="special">/</span><span class="identifier">bind_member_function</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Binding member functions can be done similarly. A bound member function takes
+        in a pointer or reference to an object as the first argument. For instance,
+        given:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">xyz</span> 
+<span class="special">{</span> 
+    <span class="keyword">void</span> <span class="identifier">foo</span><span class="special">(</span><span class="keyword">int</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span> 
+<span class="special">};</span>
+</pre>
+<p>
+        <tt class="computeroutput"><span class="identifier">xyz</span></tt>'s <tt class="computeroutput"><span class="identifier">foo</span></tt>
+        member function can be bound as:
+      </p>
+<pre class="programlisting">
+<span class="identifier">bind</span><span class="special">(&</span><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">foo</span><span class="special">,</span> <span class="identifier">obj</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">)</span> <span class="comment">// obj is an xyz object
+</span></pre>
+<p>
+        Take note that a lazy-member functions expects the first argument to be a
+        pointer or reference to an object. Both the object (reference or pointer)
+        and the arguments can be lazily bound. Examples:
+      </p>
+<pre class="programlisting">
+<span class="identifier">xyz</span> <span class="identifier">obj</span><span class="special">;</span>
+<span class="identifier">bind</span><span class="special">(&</span><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">foo</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)</span>     <span class="comment">// arg1.foo(arg2)
+</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">foo</span><span class="special">,</span> <span class="identifier">obj</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">)</span>      <span class="comment">// obj.foo(arg1)
+</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">foo</span><span class="special">,</span> <span class="identifier">obj</span><span class="special">,</span> <span class="number">100</span><span class="special">)</span>       <span class="comment">// obj.foo(100)
+</span></pre>
+<a name="phoenix.composite.bind.binding_member_variables"></a><h2>
+<a name="id467594"></a>
+        Binding Member Variables
+      </h2>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">bind</span><span class="special">/</span><span class="identifier">bind_member_variable</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Member variables can also be bound much like member functions. Member variables
+        are not functions. Yet, like the ref(x) that acts like a nullary function
+        returning a reference to the data, member variables, when bound, act like
+        a unary function, taking in a pointer or reference to an object as its argument
+        and returning a reference to the bound member variable. For instance, given:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">xyz</span> 
+<span class="special">{</span> 
+    <span class="keyword">int</span> <span class="identifier">v</span><span class="special">;</span> 
+<span class="special">};</span>
+</pre>
+<p>
+        <tt class="computeroutput"><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">v</span></tt> can be bound as:
+      </p>
+<pre class="programlisting">
+<span class="identifier">bind</span><span class="special">(&</span><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">obj</span><span class="special">)</span> <span class="comment">// obj is an xyz object
+</span></pre>
+<p>
+        As noted, just like the bound member function, a bound member variable also
+        expects the first (and only) argument to be a pointer or reference to an
+        object. The object (reference or pointer) can be lazily bound. Examples:
+      </p>
+<pre class="programlisting">
+<span class="identifier">xyz</span> <span class="identifier">obj</span><span class="special">;</span>
+<span class="identifier">bind</span><span class="special">(&</span><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">)</span>             <span class="comment">// arg1.v 
+</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">obj</span><span class="special">)</span>              <span class="comment">// obj.v  
+</span><span class="identifier">bind</span><span class="special">(&</span><span class="identifier">xyz</span><span class="special">::</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">)(</span><span class="identifier">obj</span><span class="special">)</span> <span class="special">=</span> <span class="number">4</span>    <span class="comment">// obj.v = 4
+</span></pre>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="primitives.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="container.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/inside_phoenix.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/inside_phoenix.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,750 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Inside Phoenix</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="algorithm.html" title="Algorithm">
+<link rel="next" href="wrap_up.html" title="Wrap Up">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="algorithm.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="wrap_up.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.inside_phoenix"></a>Inside Phoenix</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">Actors In Detail</span></dt>
+<dt><span class="section">Actor Example</span></dt>
+<dt><span class="section">Composites In Detail</span></dt>
+<dt><span class="section">Composing</span></dt>
+<dt><span class="section">Extending</span></dt>
+</dl></div>
+<p>
+      This chapter explains in more detail how the library operates. The information
+      henceforth should not be necessary to those who are interested in just using
+      the library. However, a microscopic view might prove to be beneficial to moderate
+      to advanced programmers who wish to extend the library.
+    </p>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.inside_phoenix.actors_in_detail"></a>Actors In Detail</h3></div></div></div>
+<a name="phoenix.inside_phoenix.actors_in_detail.actor_concept"></a><h3>
+<a name="id479686"></a>
+        Actor Concept
+      </h3>
+<p>
+        The main concept is the <tt class="computeroutput"><span class="identifier">Actor</span></tt>.
+        Actors are function objects (that can accept 0 to N arguments (where N is
+        a predefined maximum).
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> You can set <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt>,
+              the predefined maximum arity an actor can take. By default, <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt> is set to 10.</td></tr></tbody>
+</table></div>
+<a name="phoenix.inside_phoenix.actors_in_detail.actor_template_class"></a><h3>
+<a name="id479780"></a>
+        actor template class
+      </h3>
+<p>
+        The <tt class="computeroutput"><span class="identifier">actor</span></tt> template class
+        models the <tt class="computeroutput"><span class="identifier">Actor</span></tt> concept:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Eval</span><span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">actor</span> <span class="special">:</span> <span class="identifier">Eval</span>
+<span class="special">{</span>
+    <span class="keyword">typedef</span> <span class="identifier">Eval</span> <span class="identifier">eval_type</span><span class="special">;</span>
+
+    <span class="identifier">actor</span><span class="special">();</span>
+    <span class="identifier">actor</span><span class="special">(</span><span class="identifier">Eval</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">base</span><span class="special">);</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">></span>
+    <span class="keyword">explicit</span> <span class="identifier">actor</span><span class="special">(</span><span class="identifier">T0</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">);</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">></span>
+    <span class="identifier">actor</span><span class="special">(</span><span class="identifier">T0</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">T1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">_1</span><span class="special">);</span>
+    
+    <span class="comment">// more constructors
+</span>
+    <span class="keyword">typename</span> <span class="identifier">apply_actor</span><span class="special"><</span><span class="identifier">eval_type</span><span class="special">,</span> <span class="identifier">basic_environment</span><span class="special"><></span> <span class="special">>::</span><span class="identifier">type</span>
+    <span class="keyword">operator</span><span class="special">()()</span> <span class="keyword">const</span><span class="special">;</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">></span>
+    <span class="keyword">typename</span> <span class="identifier">apply_actor</span><span class="special"><</span><span class="identifier">eval_type</span><span class="special">,</span> <span class="identifier">basic_environment</span><span class="special"><</span><span class="identifier">T0</span><span class="special">></span> <span class="special">>::</span><span class="identifier">type</span>
+    <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">></span>
+    <span class="keyword">typename</span> <span class="identifier">apply_actor</span><span class="special"><</span><span class="identifier">eval_type</span><span class="special">,</span> <span class="identifier">basic_environment</span><span class="special"><</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">></span> <span class="special">>::</span><span class="identifier">type</span>
+    <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&</span> <span class="identifier">_1</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+
+    <span class="comment">// function call operators
+</span><span class="special">};</span>
+</pre>
+<div class="informaltable">
+<h4>
+<a name="id480555"></a>
+          <span class="table-title">Actor Concept Requirements</span>
+        </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Expression</th>
+<th>Result/Semantics</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">eval_type</span></tt></td>
+<td>The actor's
+              Eval type</td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">T</span><span class="special">()</span></tt></td>
+<td>Default
+              Constructor</td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">T</span><span class="special">(</span><span class="identifier">base</span><span class="special">)</span></tt></td>
+<td>Constructor
+              from Eval</td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">T</span><span class="special">(</span><span class="identifier">arg0</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">argN</span><span class="special">)</span></tt></td>
+<td>Pass through constructors</td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">x</span><span class="special">(</span><span class="identifier">arg0</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">argN</span><span class="special">)</span></tt></td>
+<td>Function call operators</td>
+</tr>
+</tbody>
+</table>
+</div>
+<a name="phoenix.inside_phoenix.actors_in_detail.eval_concept"></a><h3>
+<a name="id480807"></a>
+        Eval Concept
+      </h3>
+<p>
+        The <tt class="computeroutput"><span class="identifier">actor</span></tt> template class
+        has a single template parameter, <tt class="computeroutput"><span class="identifier">Eval</span></tt>,
+        from which it derives from. While the <tt class="computeroutput"><span class="identifier">Actor</span></tt>
+        concept represents a function, the <tt class="computeroutput"><span class="identifier">Eval</span></tt>
+        concept represents the function body. The requirements for <tt class="computeroutput"><span class="identifier">Eval</span></tt> are intentionally kept simple, to
+        make it easy to write models of the concept. We shall see an example in the
+        next section.
+      </p>
+<div class="informaltable">
+<h4>
+<a name="id480890"></a>
+          <span class="table-title">Eval Concept Requirements</span>
+        </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Expression</th>
+<th>Result/Semantics</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="keyword">return</span> <span class="identifier">x</span><span class="special">.</span><span class="identifier">eval</span><span class="special">(</span><span class="identifier">env</span><span class="special">)</span></tt></td>
+<td>Evaluates the function
+              (see Environment below)</td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">result</span><span class="special"><</span><span class="identifier">Env</span><span class="special">>::</span><span class="identifier">type</span></tt></td>
+<td>The return type
+              of eval (see Environment below)</td>
+</tr>
+</tbody>
+</table>
+</div>
+<a name="phoenix.inside_phoenix.actors_in_detail.constructors"></a><h3>
+<a name="id481035"></a>
+        Constructors
+      </h3>
+<p>
+        In addition to a default constructor and an constructor from a Eval object,
+        there are templated (pass through) constructors for 1 to N arguments (N ==
+        <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt>). These constructors
+        simply forward the arguments to the <tt class="computeroutput"><span class="identifier">base</span></tt>.
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Parametric Base Class
+              Pattern</b></span><br> <br> Notice that actor derives from its
+              template argument Eval. This is the inverse of the curiously recurring
+              template pattern (CRTP). With the CRTP, a class, T, has a Derived template
+              parameter that is assumed to be its subclass. The "parametric
+              base class pattern" (PBCP), on the other hand, inverses the inheritance
+              and makes a class, T, the derived class. Both CRTP and PBCP techniques
+              have its pros and cons, which is outside the scope of this document.
+              CRTP should really be renamed "parametric subclass pattern (PSCP),
+              but again, that's another story. </td></tr></tbody>
+</table></div>
+<a name="phoenix.inside_phoenix.actors_in_detail.function_call_operators"></a><h3>
+<a name="id481142"></a>
+        Function Call Operators
+      </h3>
+<p>
+        There are N function call operators for 0 to N arguments (N == <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt>). The actor class accepts
+        the arguments and forwards the arguments to the actor's base <tt class="computeroutput"><span class="identifier">Eval</span></tt> for evaluation.
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> <span class="bold"><b>Forwarding Function
+              Problem</b></span><br> <br> The function call operators cannot
+              accept non-const temporaries and literal constants. There is a known
+              issue with current C++ called the "<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm" target="_top">Forwarding
+              Function Problem</a>". The problem is that given an arbitrary
+              function <tt class="computeroutput"><span class="identifier">F</span></tt>, using current
+              C++ language rules, one cannot create a forwarding function <tt class="computeroutput"><span class="identifier">FF</span></tt> that transparently assumes the
+              arguments of <tt class="computeroutput"><span class="identifier">F</span></tt>. Disallowing
+              non-const rvalues arguments partially solves the problem but prohibits
+              code such as <tt class="computeroutput"><span class="identifier">f</span><span class="special">(</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">,</span> <span class="number">3</span><span class="special">);</span></tt>.
+              </td></tr></tbody>
+</table></div>
+<a name="phoenix.inside_phoenix.actors_in_detail.environment"></a><h3>
+<a name="id481329"></a>
+        Environment
+      </h3>
+<p>
+        On an actor function call, before calling the actor's <tt class="computeroutput"><span class="identifier">Eval</span><span class="special">::</span><span class="identifier">eval</span></tt>
+        for evaluation, the actor creates an <span class="emphasis"><em><span class="bold"><b>environment</b></span></em></span>.
+        Basically, the environment packages the arguments in a tuple. The <tt class="computeroutput"><span class="identifier">Environment</span></tt> is a concept, of which, the
+        <tt class="computeroutput"><span class="identifier">basic_environment</span></tt> template
+        class is a model of.
+      </p>
+<div class="informaltable">
+<h4>
+<a name="id481397"></a>
+          <span class="table-title">Environment Concept Requirements</span>
+        </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Expression</th>
+<th>Result/Semantics</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">x</span><span class="special">.</span><span class="identifier">args</span><span class="special">()</span></tt></td>
+<td>The
+              arguments in a tie (a tuple of references)</td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">args_type</span></tt></td>
+<td>The arguments'
+              types in an MPL sequence</td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">tie_type</span></tt></td>
+<td>The tie (tuple
+              of references) type</td>
+</tr>
+</tbody>
+</table>
+</div>
+<p>
+        Schematically:
+      </p>
+<p>
+        <span class="inlinemediaobject"><img src="../images/funnel_in.png" alt="funnel_in"></span>
+      </p>
+<p>
+        Other parts of the library (e.g. the scope module) extends the <tt class="computeroutput"><span class="identifier">Environment</span></tt> concept to hold other information
+        such as local variables, etc.
+      </p>
+<a name="phoenix.inside_phoenix.actors_in_detail.apply_actor"></a><h3>
+<a name="id481574"></a>
+        apply_actor
+      </h3>
+<p>
+        <tt class="computeroutput"><span class="identifier">apply_actor</span></tt> is a standard
+        MPL style metafunction that simply calls the Action's <tt class="computeroutput"><span class="identifier">result</span></tt>
+        nested metafunction:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Action</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">apply_actor</span>
+<span class="special">{</span>
+    <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Action</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">result</span><span class="special"><</span><span class="identifier">Env</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">type</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+<p>
+        After evaluating the arguments and doing some computation, the <tt class="computeroutput"><span class="identifier">eval</span></tt> member function returns something
+        back to the client. To do this, the forwarding function (the actor's <tt class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></tt>)
+        needs to know the return type of the eval member function that it is calling.
+        For this purpose, models of <tt class="computeroutput"><span class="identifier">Eval</span></tt>
+        are required to provide a nested template class:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">result</span><span class="special">;</span>
+</pre>
+<p>
+        This nested class provides the result type information returned by the <tt class="computeroutput"><span class="identifier">Eval</span></tt>'s <tt class="computeroutput"><span class="identifier">eval</span></tt>
+        member function. The nested template class <tt class="computeroutput"><span class="identifier">result</span></tt>
+        should have a typedef <tt class="computeroutput"><span class="identifier">type</span></tt>
+        that reflects the return type of its member function <tt class="computeroutput"><span class="identifier">eval</span></tt>.
+      </p>
+<p>
+        For reference, here's a typical <tt class="computeroutput"><span class="identifier">actor</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></tt> that accepts two arguments:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">></span>
+<span class="keyword">typename</span> <span class="identifier">apply_actor</span><span class="special"><</span><span class="identifier">eval_type</span><span class="special">,</span> <span class="identifier">basic_environment</span><span class="special"><</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">></span> <span class="special">>::</span><span class="identifier">type</span>
+<span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&</span> <span class="identifier">_1</span><span class="special">)</span> <span class="keyword">const</span>
+<span class="special">{</span>
+    <span class="keyword">return</span> <span class="identifier">eval_type</span><span class="special">::</span><span class="identifier">eval</span><span class="special">(</span><span class="identifier">basic_environment</span><span class="special"><</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">>(</span><span class="identifier">_0</span><span class="special">,</span> <span class="identifier">_1</span><span class="special">));</span>
+<span class="special">}</span>
+</pre>
+<a name="phoenix.inside_phoenix.actors_in_detail.actor_result"></a><h3>
+<a name="id482224"></a>
+        actor_result
+      </h3>
+<p>
+        For reasons of symmetry to the family of <tt class="computeroutput"><span class="identifier">actor</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></tt> there is a special metafunction usable
+        for actor result type calculation named <tt class="computeroutput"><span class="identifier">actor_result</span></tt>.
+        This metafunction allows us to directly to specify the types of the parameters
+        to be passed to the <tt class="computeroutput"><span class="identifier">actor</span><span class="special">::</span><span class="keyword">operator</span><span class="special">()</span></tt> function. Here's a typical <tt class="computeroutput"><span class="identifier">actor_result</span></tt> that accepts two arguments:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Action</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">T1</span><span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">actor_result</span>
+<span class="special">{</span>
+    <span class="keyword">typedef</span> <span class="identifier">basic_environment</span><span class="special"><</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">></span> <span class="identifier">env_type</span><span class="special">;</span>
+    <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">Action</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">result</span><span class="special"><</span><span class="identifier">env_type</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">type</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.inside_phoenix.actor_example"></a>Actor Example</h3></div></div></div>
+<p>
+        Let us see a very simple prototypical example of an actor. This is not a
+        toy example. This is actually part of the library. Remember the reference?.
+      </p>
+<p>
+        First, we have a model of the <tt class="computeroutput"><span class="identifier">Eval</span></tt>
+        concept: the <tt class="computeroutput"><span class="identifier">reference</span></tt>:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">reference</span>
+<span class="special">{</span>
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">></span>
+    <span class="keyword">struct</span> <span class="identifier">result</span>
+    <span class="special">{</span>
+        <span class="keyword">typedef</span> <span class="identifier">T</span><span class="special">&</span> <span class="identifier">type</span><span class="special">;</span>
+    <span class="special">};</span>
+
+    <span class="identifier">reference</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">arg</span><span class="special">)</span>
+        <span class="special">:</span> <span class="identifier">ref</span><span class="special">(</span><span class="identifier">arg</span><span class="special">)</span> <span class="special">{}</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">></span>
+    <span class="identifier">T</span><span class="special">&</span> <span class="identifier">eval</span><span class="special">(</span><span class="identifier">Env</span> <span class="keyword">const</span><span class="special">&)</span> <span class="keyword">const</span>
+    <span class="special">{</span>
+        <span class="keyword">return</span> <span class="identifier">ref</span><span class="special">;</span>
+    <span class="special">}</span>
+
+    <span class="identifier">T</span><span class="special">&</span> <span class="identifier">ref</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+<p>
+        Models of <tt class="computeroutput"><span class="identifier">Eval</span></tt> are never
+        created directly and its instances never exist alone. We have to wrap it
+        inside the <tt class="computeroutput"><span class="identifier">actor</span></tt> template
+        class to be useful. The <tt class="computeroutput"><span class="identifier">ref</span></tt>
+        template function does this for us:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">></span>
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">></span> <span class="keyword">const</span>
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">v</span><span class="special">)</span>
+<span class="special">{</span>
+    <span class="keyword">return</span> <span class="identifier">reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">>(</span><span class="identifier">v</span><span class="special">);</span>
+<span class="special">}</span>
+</pre>
+<p>
+        The <tt class="computeroutput"><span class="identifier">reference</span></tt> template class
+        conforms to the Eval concept. It has a nested <tt class="computeroutput"><span class="identifier">result</span></tt> metafunction that reflects the return
+        type of its <tt class="computeroutput"><span class="identifier">eval</span></tt> member function,
+        which peforms the actual function. <tt class="computeroutput"><span class="identifier">reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span></tt>
+        stores a reference to a <tt class="computeroutput"><span class="identifier">T</span></tt>.
+        Its <tt class="computeroutput"><span class="identifier">eval</span></tt> member function
+        simply returns the reference. It does not make use of the environment <tt class="computeroutput"><span class="identifier">Env</span></tt>.
+      </p>
+<p>
+        <span class="emphasis"><em>Pretty simple...</em></span>
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.inside_phoenix.composites_in_detail"></a>Composites In Detail</h3></div></div></div>
+<p>
+        We stated before that composites are actors that are composed of zero or
+        more actors (see Composite). This
+        is not quite accurate. The definition was sufficient at that point where
+        we opted to keep things simple and not bury the reader with details which
+        she might not need anyway.
+      </p>
+<p>
+        Actually, a composite is a model of the Eval concept (more on this later).
+        At the same time, it is also composed of 0..N (where N is a predefined maximum)
+        Eval instances and an eval policy.
+        The individual Eval instances are stored in a tuple.
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> In a sense, the original definition of "composite",
+              more or less, will do just fine because Eval instances never exist
+              alone and are always wrapped in an <tt class="computeroutput"><span class="identifier">actor</span></tt>
+              template class which inherits from it anyway. The resulting actor IS-AN
+              Eval.</td></tr></tbody>
+</table></div>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> You can set <tt class="computeroutput"><span class="identifier">PHOENIX_COMPOSITE_LIMIT</span></tt>,
+              the predefined maximum <tt class="computeroutput"><span class="identifier">Eval</span></tt>s
+              (actors) a composite can take. By default, <tt class="computeroutput"><span class="identifier">PHOENIX_COMPOSITE_LIMIT</span></tt>
+              is set to <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt>
+              (See Actors).</td></tr></tbody>
+</table></div>
+<a name="phoenix.inside_phoenix.composites_in_detail.composite_template_class"></a><h2>
+<a name="id483520"></a>
+        composite template class
+      </h2>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">EvalPolicy</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">EvalTuple</span><span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">composite</span> <span class="special">:</span> <span class="identifier">EvalTuple</span>
+<span class="special">{</span>
+    <span class="keyword">typedef</span> <span class="identifier">EvalTuple</span> <span class="identifier">base_type</span><span class="special">;</span>
+    <span class="keyword">typedef</span> <span class="identifier">EvalPolicy</span> <span class="identifier">eval_policy_type</span><span class="special">;</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">></span>
+    <span class="keyword">struct</span> <span class="identifier">result</span>
+    <span class="special">{</span>
+        <span class="keyword">typedef</span> <span class="identifier">implementation</span><span class="special">-</span><span class="identifier">defined</span> <span class="identifier">type</span><span class="special">;</span>
+    <span class="special">};</span>
+
+    <span class="identifier">composite</span><span class="special">();</span>
+    <span class="identifier">composite</span><span class="special">(</span><span class="identifier">base_type</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">actors</span><span class="special">);</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">U0</span><span class="special">></span>
+    <span class="identifier">composite</span><span class="special">(</span><span class="identifier">U0</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">);</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">U0</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">U1</span><span class="special">></span>
+    <span class="identifier">composite</span><span class="special">(</span><span class="identifier">U0</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">U1</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">_1</span><span class="special">);</span>
+    
+    <span class="comment">// more constructors
+</span>
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">></span>
+    <span class="keyword">typename</span> <span class="identifier">result</span><span class="special"><</span><span class="identifier">Env</span><span class="special">>::</span><span class="identifier">type</span>
+    <span class="identifier">eval</span><span class="special">(</span><span class="identifier">Env</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">env</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
+<span class="special">};</span>
+</pre>
+<a name="phoenix.inside_phoenix.composites_in_detail.evaltuple"></a><h2>
+<a name="id484112"></a>
+        EvalTuple
+      </h2>
+<p>
+        <tt class="computeroutput"><span class="identifier">EvalTuple</span></tt>, holds all the
+        Eval instances. The <tt class="computeroutput"><span class="identifier">composite</span></tt> template class inherits from
+        it. In addition to a default constructor and a constructor from an <tt class="computeroutput"><span class="identifier">EvalTuple</span></tt> object, there are templated (pass
+        through) constructors for 1 to N arguments (again, where N == <tt class="computeroutput"><span class="identifier">PHOENIX_COMPOSITE_LIMIT</span></tt>). These constructors
+        simply forward the arguments to the <tt class="computeroutput"><span class="identifier">EvalTuple</span></tt>
+        base class.
+      </p>
+<a name="phoenix.inside_phoenix.composites_in_detail.evalpolicy"></a><h2>
+<a name="id484203"></a>
+        EvalPolicy
+      </h2>
+<p>
+        The composite's <tt class="computeroutput"><span class="identifier">eval</span></tt> member
+        function calls its <tt class="computeroutput"><span class="identifier">EvalPolicy</span></tt>'s
+        <tt class="computeroutput"><span class="identifier">eval</span></tt> member function (a static
+        member function) passing in the environment
+        and each of its actors, in parallel. The following diagram illustrates what's
+        happening:
+      </p>
+<p>
+        <span class="inlinemediaobject"><img src="../images/funnel_out.png" alt="funnel_out"></span>
+      </p>
+<div class="informaltable">
+<h4>
+<a name="id484285"></a>
+          <span class="table-title">EvalPolicy Requirements</span>
+        </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Expression</th>
+<th>Result/Semantics</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">x</span><span class="special">.</span><span class="identifier">eval</span><span class="special"><</span><span class="identifier">RT</span><span class="special">>(</span><span class="identifier">env</span><span class="special">,</span> <span class="identifier">eval0</span><span class="special">,</span> <span class="identifier">eval1</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">evalN</span><span class="special">)</span></tt></td>
+<td>Evaluate the composite</td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">T</span><span class="special">::</span><span class="identifier">result</span><span class="special"><</span><span class="identifier">Env</span><span class="special">,</span> <span class="identifier">Eval0</span><span class="special">,</span> <span class="identifier">Eval1</span><span class="special">,</span> <span class="identifier">Eval2</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">EvalN</span><span class="special">>::</span><span class="identifier">type</span></tt></td>
+<td>The
+              return type of eval</td>
+</tr>
+</tbody>
+</table>
+</div>
+<p>
+        The <tt class="computeroutput"><span class="identifier">EvalPolicy</span></tt> is expected
+        to have a nested template class <tt class="computeroutput"><span class="identifier">result</span></tt>
+        which has a typedef <tt class="computeroutput"><span class="identifier">type</span></tt>
+        that reflects the return type of its member function <tt class="computeroutput"><span class="identifier">eval</span></tt>.
+        Here's a typical example of the composite's eval member function for a 2-actor
+        composite:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">></span>
+<span class="keyword">typename</span> <span class="identifier">result</span><span class="special"><</span><span class="identifier">Env</span><span class="special">>::</span><span class="identifier">type</span>
+<span class="identifier">eval</span><span class="special">(</span><span class="identifier">Env</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">env</span><span class="special">)</span> <span class="keyword">const</span>
+<span class="special">{</span>
+    <span class="keyword">typedef</span> <span class="keyword">typename</span> <span class="identifier">result</span><span class="special"><</span><span class="identifier">Env</span><span class="special">>::</span><span class="identifier">type</span> <span class="identifier">return_type</span><span class="special">;</span>
+    <span class="keyword">return</span> <span class="identifier">EvalPolicy</span><span class="special">::</span><span class="keyword">template</span> 
+        <span class="identifier">eval</span><span class="special"><</span><span class="identifier">return_type</span><span class="special">>(</span>
+            <span class="identifier">env</span>
+          <span class="special">,</span> <span class="identifier">get</span><span class="special"><</span><span class="number">0</span><span class="special">>(*</span><span class="keyword">this</span><span class="special">)</span>   <span class="comment">// gets the 0th element from EvalTuple
+</span>          <span class="special">,</span> <span class="identifier">get</span><span class="special"><</span><span class="number">1</span><span class="special">>(*</span><span class="keyword">this</span><span class="special">));</span> <span class="comment">// gets the 1st element from EvalTuple    
+</span><span class="special">}</span>
+</pre>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.inside_phoenix.composing"></a>Composing</h3></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">compose</span></dt>
+<dt><span class="section">as_composite</span></dt>
+<dt><span class="section">Composite Example</span></dt>
+</dl></div>
+<p>
+        Composites are never instantiated directly. Front end expression templates
+        are used to generate the composites. Using expression templates, we implement
+        a DSEL (Domain Specific Embedded Language) that mimicks native C++. You've
+        seen this DSEL in action in the preceding sections. It is most evident in
+        the Statement section.
+      </p>
+<p>
+        There are some facilities in the library to make composition of composites
+        easier. We have a set of overloaded <tt class="computeroutput"><span class="identifier">compose</span></tt>
+        functions and an <tt class="computeroutput"><span class="identifier">as_composite</span></tt>
+        metafunction. Together, these helpers make composing a breeze. We'll provide
+        an <a href="inside_phoenix.html#phoenix.inside_phoenix.composing.composite_example" title="Composite Example">example
+        of a composite</a> later to see why.
+      </p>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.inside_phoenix.composing.compose"></a>compose</h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">compose</span><span class="special"><</span><span class="identifier">EvalPolicy</span><span class="special">>(</span><span class="identifier">arg0</span><span class="special">,</span> <span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">argN</span><span class="special">);</span>
+</pre>
+<p>
+          Given an EvalPolicy and some arguments
+          <tt class="computeroutput"><span class="identifier">arg0</span></tt>...argN, returns a
+          proper <tt class="computeroutput"><span class="identifier">composite</span></tt>. The arguments
+          may or may not be phoenix actors (primitives of composites). If not, the
+          arguments are converted to actors appropriately. For example:
+        </p>
+<pre class="programlisting">
+<span class="identifier">compose</span><span class="special"><</span><span class="identifier">X</span><span class="special">>(</span><span class="number">3</span><span class="special">)</span>
+</pre>
+<p>
+          converts the argument <tt class="computeroutput"><span class="number">3</span></tt> to
+          an <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">value</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">>(</span><span class="number">3</span><span class="special">)</span></tt>.
+        </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.inside_phoenix.composing.as_composite"></a>as_composite</h4></div></div></div>
+<pre class="programlisting">
+<span class="identifier">as_composite</span><span class="special"><</span><span class="identifier">EvalPolicy</span><span class="special">,</span> <span class="identifier">Arg0</span><span class="special">,</span> <span class="identifier">Arg1</span><span class="special">,</span> <span class="identifier">Arg2</span><span class="special">,</span> <span class="special">...,</span> <span class="identifier">ArgN</span><span class="special">>::</span><span class="identifier">type</span>
+</pre>
+<p>
+          This is the metafunction counterpart of <tt class="computeroutput"><span class="identifier">compose</span></tt>.
+          Given an EvalPolicy and some argument types
+          <tt class="computeroutput"><span class="identifier">Arg0</span></tt>...ArgN, returns a
+          proper <tt class="computeroutput"><span class="identifier">composite</span></tt> type.
+          For example:
+        </p>
+<pre class="programlisting">
+<span class="identifier">as_composite</span><span class="special"><</span><span class="identifier">X</span><span class="special">,</span> <span class="keyword">int</span><span class="special">>::</span><span class="identifier">type</span>
+</pre>
+<p>
+          is the composite type of the <tt class="computeroutput"><span class="identifier">compose</span><span class="special"><</span><span class="identifier">X</span><span class="special">>(</span><span class="number">3</span><span class="special">)</span></tt>
+          expression above.
+        </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h4 class="title">
+<a name="phoenix.inside_phoenix.composing.composite_example"></a>Composite Example</h4></div></div></div>
+<p>
+          Now, let's examine an example. Again, this is not a toy example. This is
+          actually part of the library. Remember the while_ lazy statement? Putting
+          together everything we've learned so far, we will present it here in its
+          entirety (verbatim):
+        </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">while_eval</span>
+<span class="special">{</span>
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Cond</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Do</span><span class="special">></span>
+    <span class="keyword">struct</span> <span class="identifier">result</span>
+    <span class="special">{</span>
+        <span class="keyword">typedef</span> <span class="keyword">void</span> <span class="identifier">type</span><span class="special">;</span>
+    <span class="special">};</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">RT</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Cond</span><span class="special">,</span> <span class="keyword">typename</span> <span class="identifier">Do</span><span class="special">></span>
+    <span class="keyword">static</span> <span class="keyword">void</span>
+    <span class="identifier">eval</span><span class="special">(</span><span class="identifier">Env</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">env</span><span class="special">,</span> <span class="identifier">Cond</span><span class="special">&</span> <span class="identifier">cond</span><span class="special">,</span> <span class="identifier">Do</span><span class="special">&</span> <span class="identifier">do_</span><span class="special">)</span>
+    <span class="special">{</span>
+        <span class="keyword">while</span> <span class="special">(</span><span class="identifier">cond</span><span class="special">.</span><span class="identifier">eval</span><span class="special">(</span><span class="identifier">env</span><span class="special">))</span>
+            <span class="identifier">do_</span><span class="special">.</span><span class="identifier">eval</span><span class="special">(</span><span class="identifier">env</span><span class="special">);</span>
+    <span class="special">}</span>
+<span class="special">};</span>
+
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Cond</span><span class="special">></span>
+<span class="keyword">struct</span> <span class="identifier">while_gen</span>
+<span class="special">{</span>
+    <span class="identifier">while_gen</span><span class="special">(</span><span class="identifier">Cond</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">cond</span><span class="special">)</span>
+        <span class="special">:</span> <span class="identifier">cond</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span> <span class="special">{}</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Do</span><span class="special">></span>
+    <span class="identifier">actor</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">as_composite</span><span class="special"><</span><span class="identifier">while_eval</span><span class="special">,</span> <span class="identifier">Cond</span><span class="special">,</span> <span class="identifier">Do</span><span class="special">>::</span><span class="identifier">type</span><span class="special">></span>
+    <span class="keyword">operator</span><span class="special">[](</span><span class="identifier">Do</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">do_</span><span class="special">)</span> <span class="keyword">const</span>
+    <span class="special">{</span>
+        <span class="keyword">return</span> <span class="identifier">compose</span><span class="special"><</span><span class="identifier">while_eval</span><span class="special">>(</span><span class="identifier">cond</span><span class="special">,</span> <span class="identifier">do_</span><span class="special">);</span>
+    <span class="special">}</span>
+
+    <span class="identifier">Cond</span> <span class="identifier">cond</span><span class="special">;</span>
+<span class="special">};</span>
+
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Cond</span><span class="special">></span>
+<span class="identifier">while_gen</span><span class="special"><</span><span class="identifier">Cond</span><span class="special">></span>
+<span class="identifier">while_</span><span class="special">(</span><span class="identifier">Cond</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">cond</span><span class="special">)</span>
+<span class="special">{</span>
+    <span class="keyword">return</span> <span class="identifier">while_gen</span><span class="special"><</span><span class="identifier">Cond</span><span class="special">>(</span><span class="identifier">cond</span><span class="special">);</span>
+<span class="special">}</span>
+</pre>
+<p>
+          <tt class="computeroutput"><span class="identifier">while_eval</span></tt> is an example
+          of an EvalPolicy. <tt class="computeroutput"><span class="identifier">while_gen</span></tt>
+          and <tt class="computeroutput"><span class="identifier">while_</span></tt> are the expression
+          template front ends. Let's break this apart to understand what's happening.
+          Let's start at the bottom. It's easier that way.
+        </p>
+<p>
+          When you write:
+        </p>
+<pre class="programlisting">
+<span class="identifier">while_</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span>
+</pre>
+<p>
+          we generate an instance of <tt class="computeroutput"><span class="identifier">while_gen</span><span class="special"><</span><span class="identifier">Cond</span><span class="special">></span></tt>, where <tt class="computeroutput"><span class="identifier">Cond</span></tt>
+          is the type of <tt class="computeroutput"><span class="identifier">cond</span></tt>. <tt class="computeroutput"><span class="identifier">cond</span></tt> can be an arbitrarily complex actor
+          expression. The <tt class="computeroutput"><span class="identifier">while_gen</span></tt>
+          template class has an <tt class="computeroutput"><span class="keyword">operator</span><span class="special">[]</span></tt> accepting another expression. If we write:
+        </p>
+<pre class="programlisting">
+<span class="identifier">while_</span><span class="special">(</span><span class="identifier">cond</span><span class="special">)</span>
+<span class="special">[</span>
+    <span class="identifier">do_</span>
+<span class="special">]</span>
+</pre>
+<p>
+          it will generate a proper composite with the type:
+        </p>
+<pre class="programlisting">
+<span class="identifier">as_composite</span><span class="special"><</span><span class="identifier">while_eval</span><span class="special">,</span> <span class="identifier">Cond</span><span class="special">,</span> <span class="identifier">Do</span><span class="special">>::</span><span class="identifier">type</span>
+</pre>
+<p>
+          where <tt class="computeroutput"><span class="identifier">Cond</span></tt> is the type
+          of <tt class="computeroutput"><span class="identifier">cond</span></tt> and <tt class="computeroutput"><span class="identifier">Do</span></tt> is the type of <tt class="computeroutput"><span class="identifier">do_</span></tt>.
+          Notice how we are using phoenix's composition
+          (<tt class="computeroutput"><span class="identifier">compose</span></tt> and <tt class="computeroutput"><span class="identifier">as_composite</span></tt>) mechanisms here
+        </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Do</span><span class="special">></span>
+<span class="identifier">actor</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">as_composite</span><span class="special"><</span><span class="identifier">while_eval</span><span class="special">,</span> <span class="identifier">Cond</span><span class="special">,</span> <span class="identifier">Do</span><span class="special">>::</span><span class="identifier">type</span><span class="special">></span>
+<span class="keyword">operator</span><span class="special">[](</span><span class="identifier">Do</span> <span class="keyword">const</span><span class="special">&</span> <span class="identifier">do_</span><span class="special">)</span> <span class="keyword">const</span>
+<span class="special">{</span>
+    <span class="keyword">return</span> <span class="identifier">compose</span><span class="special"><</span><span class="identifier">while_eval</span><span class="special">>(</span><span class="identifier">cond</span><span class="special">,</span> <span class="identifier">do_</span><span class="special">);</span>
+<span class="special">}</span>
+</pre>
+<p>
+          Finally, the <tt class="computeroutput"><span class="identifier">while_eval</span></tt>
+          does its thing:
+        </p>
+<pre class="programlisting">
+<span class="keyword">while</span> <span class="special">(</span><span class="identifier">cond</span><span class="special">.</span><span class="identifier">eval</span><span class="special">(</span><span class="identifier">env</span><span class="special">))</span>
+    <span class="identifier">do_</span><span class="special">.</span><span class="identifier">eval</span><span class="special">(</span><span class="identifier">env</span><span class="special">);</span>
+</pre>
+<p>
+          <tt class="computeroutput"><span class="identifier">cond</span></tt> and <tt class="computeroutput"><span class="identifier">do_</span></tt>, at this point, are instances of
+          Eval. <tt class="computeroutput"><span class="identifier">cond</span></tt>
+          and <tt class="computeroutput"><span class="identifier">do_</span></tt> are the Eval elements held by the composite's
+          EvalTuple. <tt class="computeroutput"><span class="identifier">env</span></tt>
+          is the Environment.
+        </p>
+</div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.inside_phoenix.extending"></a>Extending</h3></div></div></div>
+<p>
+        We've shown how it is very easy to extend phoenix by writing new primitives
+        and composites. The modular design of Phoenix makes it extremely extensible.
+        We have seen that layer upon layer, the whole library is built on a solid
+        foundation. There are only a few simple well designed concepts that are laid
+        out like bricks. Overall, the library is designed to be extended. Everything
+        above the core layer can in fact be considered just as extensions to the
+        library. This modular design was inherited from the Spirit
+        inline parser library.
+      </p>
+<p>
+        Extension is non-intrusive. And, whenever a component or module is extended,
+        the new extension automatically becomes a first class citizen and is automatically
+        recognized by all modules and components in the library.
+      </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="algorithm.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="wrap_up.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/intrinsic.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/intrinsic.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,320 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Intrinsic</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="composite.html" title="Composite">
+<link rel="next" href="algorithm.html" title="Algorithm">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="boost.png (6897 bytes)" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="composite.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="algorithm.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.intrinsic"></a>Intrinsic</h2></div></div></div>
+<pre class="programlisting">
+<tt class="literal"><span class="preprocessor">#include</span><span class="special"> <</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">intrinsic</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt>
+</pre>
+<p>
+      The intrinsic module predefines a set of lazy functions that work on STL sequences.
+      These functions provide a mechanism for the lazy evaluation of the public member
+      functions of the STL containers. The lazy functions are thin wrappers that
+      simply forward to their respective counterparts in the STL library.
+    </p>
+<p>
+      Lazy functions are provided for all of the member functions of the following
+      containers:
+    </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+        deque
+      </li>
+<li>
+        list
+      </li>
+<li>
+        map
+      </li>
+<li>
+        multimap
+      </li>
+<li>
+        vector
+      </li>
+</ul></div>
+<p>
+      Indeed, should your class have member functions with the same names and signatures
+      as those listed below, then it will automatically be supported. To summarize,
+      lazy functions are provided for member functions:
+    </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+        assign
+      </li>
+<li>
+        at
+      </li>
+<li>
+        back
+      </li>
+<li>
+        begin
+      </li>
+<li>
+        capacity
+      </li>
+<li>
+        clear
+      </li>
+<li>
+        empty
+      </li>
+<li>
+        end
+      </li>
+<li>
+        erase
+      </li>
+<li>
+        front
+      </li>
+<li>
+        get_allocator
+      </li>
+<li>
+        insert
+      </li>
+<li>
+        key_comp
+      </li>
+<li>
+        max_size
+      </li>
+<li>
+        pop_back
+      </li>
+<li>
+        pop_front
+      </li>
+<li>
+        push_back
+      </li>
+<li>
+        push_front
+      </li>
+<li>
+        rbegin
+      </li>
+<li>
+        rend
+      </li>
+<li>
+        reserve
+      </li>
+<li>
+        resize
+      </li>
+<li>
+        size
+      </li>
+<li>
+        splice
+      </li>
+<li>
+        value_comp
+      </li>
+</ul></div>
+<p>
+      The lazy functions' names are the same as the corresponding member function.
+      The difference is that the lazy functions are free functions and therefore
+      does not use the member "dot" syntax.
+    </p>
+<div class="informaltable">
+<h4>
+<a name="id465703"></a><span class="table-title">Sample usage</span>
+</h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>"Normal" version</th>
+<th>"Lazy" version</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">my_vector</span><span class="special">.</span><span class="identifier">at</span><span class="special">(</span><span class="number">5</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">at</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span><span class="number"> 5</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">my_list</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">size</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">my_vector1</span><span class="special">.</span><span class="identifier">swap</span><span class="special">(</span><span class="identifier">my_vector2</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">swap</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span><span class="identifier"> arg2</span><span class="special">)</span></tt></td>
+</tr>
+</tbody>
+</table>
+</div>
+<p>
+      Notice that member functions with names that clash with stl algorithms are
+      absent. This will be provided in Phoenix's algorithm module.
+    </p>
+<p>
+      No support is provided here for lazy versions of <tt class="computeroutput"><span class="keyword">operator</span><span class="special">+=</span></tt>, <tt class="computeroutput"><span class="keyword">operator</span><span class="special">[]</span></tt> etc. Such operators are not specific to STL
+      containers and lazy versions can therefore be found in operators.
+    </p>
+<div class="informaltable">
+<h4>
+<a name="id465969"></a><span class="table-title">Lazy STL Intrinsic Functions</span>
+</h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Function</th>
+<th>Semantics</th>
+</tr></thead>
+<tbody>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">assign</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">,</span><span class="identifier"> c</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">assign</span><span class="special">(</span><span class="identifier">a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">,</span><span class="identifier"> c</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">at</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> i</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">at</span><span class="special">(</span><span class="identifier">i</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">back</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">back</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">begin</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">capacity</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">capacity</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">clear</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">clear</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">empty</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">empty</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">end</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">erase</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">erase</span><span class="special">(</span><span class="identifier">a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">front</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">front</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">get_allocator</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">get_allocator</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">insert</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">,</span><span class="identifier"> c</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">,</span><span class="identifier"> c</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">key_comp</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">key_comp</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">max_size</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">max_size</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">pop_back</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">pop_back</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">pop_front</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">pop_front</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> d</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">push_back</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">push_front</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> d</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">push_front</span><span class="special">(</span><span class="identifier">d</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">pop_front</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">pop_front</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">rbegin</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">rbegin</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">rend</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">rend</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">reserve</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> n</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">reserve</span><span class="special">(</span><span class="identifier">n</span><span class="special">)</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">resize</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">resize</span><span class="special">(</span><span class="identifier">a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">size</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">size</span><span class="special">()</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">splice</span><span class="special">(</span><span class="identifier">c</span><span class="special">,</span><span class="identifier"> a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">,</span><span class="identifier"> c</span><span class="special">,</span><span class="identifier"> d</span><span class="special">])</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">splice</span><span class="special">(</span><span class="identifier">a</span><span class="special">[,</span><span class="identifier"> b</span><span class="special">,</span><span class="identifier"> c</span><span class="special">,</span><span class="identifier"> d</span><span class="special">])</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="identifier">value_comp</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span></tt></td>
+<td><tt class="computeroutput"><span class="identifier">c</span><span class="special">.</span><span class="identifier">value_comp</span><span class="special">()</span></tt></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb">
+<span class="inlinemediaobject"><img src="../images/tip.png"></span>
+            Arguments in brackets denote optional parameters.</td></tr></tbody>
+</table></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="composite.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="algorithm.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/introduction.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/introduction.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,66 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Introduction</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="next" href="starter_kit.html" title="Starter Kit">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="starter_kit.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.introduction"></a>Introduction</h2></div></div></div>
+<p>
+      <span class="inlinemediaobject"><img src="../images/banner.png" alt="banner"></span>
+    </p>
+<p>
+      The Phoenix library enables FP techniques such as higher order functions,
+      <span class="emphasis"><em>lambda</em></span> (unnamed functions), <span class="emphasis"><em>currying</em></span>
+      (partial function application) and lazy evaluation in C++. The focus is more
+      on usefulness and practicality than purity, elegance and strict adherence to
+      FP principles.
+    </p>
+<p>
+      FP is a programming discipline that is not at all tied to a specific language.
+      FP as a programming discipline can, in fact, be applied to many programming
+      languages. In the realm of C++ for instance, we are seeing more FP techniques
+      being applied. C++ is sufficiently rich to support at least some of the most
+      important facets of FP. C++ is a multiparadigm programming language. It is
+      not only procedural. It is not only object oriented. Beneath the core of the
+      standard C++ library, a closer look into STL gives us a glimpse of FP already
+      in place. It is obvious that the authors of STL know and practice FP. In the
+      near future, we shall surely see more FP trickle down into the mainstream.
+    </p>
+<p>
+      The truth is, most of the FP techniques can coexist quite well with the standard
+      object oriented and imperative programming paradigms. When we are using STL
+      algorithms and functors (function objects) for example, we are already doing
+      FP. Phoenix is an evolutionary next step.
+    </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="../index.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="starter_kit.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/organization.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/organization.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,208 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Organization</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="basics.html" title="Basics">
+<link rel="next" href="actors.html" title="Actors">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="basics.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="actors.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.organization"></a>Organization</h2></div></div></div>
+<p>
+      Care and attention to detail was given, painstakingly, to the design and implementation
+      of Phoenix.
+    </p>
+<p>
+      The library is organized in four layers:
+    </p>
+<p>
+      <span class="inlinemediaobject"><img src="../images/organization.png" alt="organization"></span>
+    </p>
+<p>
+      The modules are orthogonal, with no cyclic dependencies. Lower layers do not
+      depend on higher layers. Modules in a layer do not depend on other modules
+      in the same layer. This means, for example, that Bind can be completely discarded
+      if it is not required; or one could perhaps take out Operator and Statement
+      and just use Function, which may be desireable in a pure FP application.
+    </p>
+<p>
+      The library has grown from the original Phoenix but still comprises only header
+      files. There are no object files to link against.
+    </p>
+<a name="phoenix.organization.core"></a><h2>
+<a name="id448254"></a>
+      Core
+    </h2>
+<p>
+      The lowest two layers comprise the core.
+    </p>
+<p>
+      The <tt class="computeroutput"><span class="identifier">Actor</span></tt> is the main concept
+      behind the library. Lazy functions are abstracted as actors. There are only
+      2 kinds of actors:
+    </p>
+<div class="orderedlist"><ol type="1">
+<li>
+        Primitives
+      </li>
+<li>
+        Composites
+      </li>
+</ol></div>
+<p>
+      Primitives provide the basic building blocks of functionality within Phoenix.
+      Composites are used to combine these primitives together to provide more powerful
+      functionality.
+    </p>
+<p>
+      Composites are composed of zero or more actors. Each actor in a composite can
+      again be another composite.
+    </p>
+<div class="informaltable">
+<h4>
+<a name="id448312"></a>
+        <span class="table-title">Modules</span>
+      </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Module</th>
+<th>Description</th>
+</tr></thead>
+<tbody>
+<tr>
+<td>Function</td>
+<td>Lazy functions support (e.g. <tt class="computeroutput"><span class="identifier">add</span></tt>)</td>
+</tr>
+<tr>
+<td>Operator</td>
+<td>Lazy operators support (e.g. <tt class="computeroutput"><span class="special">+</span></tt>)</td>
+</tr>
+<tr>
+<td>Statement</td>
+<td>Lazy statments (e.g. <tt class="computeroutput"><span class="identifier">if_</span></tt>,
+            <tt class="computeroutput"><span class="identifier">while_</span></tt>)</td>
+</tr>
+<tr>
+<td>Object</td>
+<td>Lazy casts (e.g. <tt class="computeroutput"><span class="identifier">static_cast_</span></tt>),
+            object creation destruction (e.g. <tt class="computeroutput"><span class="identifier">new_</span></tt>,
+            <tt class="computeroutput"><span class="identifier">delete_</span></tt>)</td>
+</tr>
+<tr>
+<td>Scope</td>
+<td>Support for scopes, local variables and lambda-lambda</td>
+</tr>
+<tr>
+<td>Bind</td>
+<td>Lazy functions from free functions, member
+            functions or member variables.</td>
+</tr>
+<tr>
+<td>Container</td>
+<td>Set of predefined "lazy" functions
+            that work on STL containers and sequences (e.g. <tt class="computeroutput"><span class="identifier">push_back</span></tt>).</td>
+</tr>
+<tr>
+<td>Algorithm</td>
+<td>Set of predefined "lazy" versions
+            of the STL algorithms (e.g. <tt class="computeroutput"><span class="identifier">find_if</span></tt>).</td>
+</tr>
+</tbody>
+</table>
+</div>
+<p>
+      Each module is defined in a header file with the same name. For example, the
+      core module is defined in <tt class="computeroutput"><span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt>.
+    </p>
+<div class="informaltable">
+<h4>
+<a name="id448597"></a>
+        <span class="table-title">Includes</span>
+      </h4>
+<table class="table">
+<colgroup>
+<col>
+<col>
+</colgroup>
+<thead><tr>
+<th>Module</th>
+<th>File</th>
+</tr></thead>
+<tbody>
+<tr>
+<td>Core</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">core</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>Function</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">function</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>Operator</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="keyword">operator</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>Statement</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">statement</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>Object</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">object</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>Scope</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">scope</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>Bind</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">bind</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>Container</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">container</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+<tr>
+<td>Algorithm</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">algorithm</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></tt></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Finer grained include files are available per feature;
+            see the succeeding sections.</td></tr></tbody>
+</table></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="basics.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="actors.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/primitives.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/primitives.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,329 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Primitives</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="actors.html" title="Actors">
+<link rel="next" href="composite.html" title="Composite">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="actors.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="composite.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.primitives"></a>Primitives</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">Arguments</span></dt>
+<dt><span class="section">Values</span></dt>
+<dt><span class="section">References</span></dt>
+<dt><span class="section">Constant References</span></dt>
+<dt><span class="section">Nothing</span></dt>
+</dl></div>
+<p>
+      Actors are composed to create more complex actors in a tree-like hierarchy.
+      The primitives are atomic entities that are like the leaves in the tree. Phoenix
+      is extensible. New primitives can be added anytime. Right out of the box, there
+      are only a few primitives. This section shall deal with these preset primitives.
+    </p>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.primitives.arguments"></a>Arguments</h3></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">core</span><span class="special">/</span><span class="identifier">argument</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        We use an instance of:
+      </p>
+<pre class="programlisting">
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="identifier">N</span><span class="special">></span> <span class="special">></span>
+</pre>
+<p>
+        to represent the Nth function argument. The argument placeholder acts as
+        an imaginary data-bin where a function argument will be placed.
+      </p>
+<a name="phoenix.primitives.arguments.predefined_arguments"></a><h2>
+<a name="id450010"></a>
+        Predefined Arguments
+      </h2>
+<p>
+        There are a few predefined instances of <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="identifier">N</span><span class="special">></span> <span class="special">></span></tt> named <tt class="computeroutput"><span class="identifier">arg1</span></tt>..<tt class="computeroutput"><span class="identifier">argN</span></tt>, and its BLL
+        counterpart <tt class="computeroutput"><span class="identifier">_1</span></tt>..<tt class="computeroutput"><span class="identifier">_N</span></tt>. (where N is a predefined maximum).
+      </p>
+<p>
+        Here are some sample preset definitions of <tt class="computeroutput"><span class="identifier">arg1</span></tt>..<tt class="computeroutput"><span class="identifier">argN</span></tt>
+      </p>
+<pre class="programlisting">
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="number">0</span><span class="special">></span> <span class="special">></span> <span class="keyword">const</span> <span class="identifier">arg1</span> <span class="special">=</span> <span class="identifier">argument</span><span class="special"><</span><span class="number">0</span><span class="special">>();</span>
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="number">1</span><span class="special">></span> <span class="special">></span> <span class="keyword">const</span> <span class="identifier">arg2</span> <span class="special">=</span> <span class="identifier">argument</span><span class="special"><</span><span class="number">1</span><span class="special">>();</span>
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="number">2</span><span class="special">></span> <span class="special">></span> <span class="keyword">const</span> <span class="identifier">arg3</span> <span class="special">=</span> <span class="identifier">argument</span><span class="special"><</span><span class="number">2</span><span class="special">>();</span>
+</pre>
+<p>
+        and its BLL <tt class="computeroutput"><span class="identifier">_1</span></tt>..<tt class="computeroutput"><span class="identifier">_N</span></tt>
+        style counterparts:
+      </p>
+<pre class="programlisting">
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="number">0</span><span class="special">></span> <span class="special">></span> <span class="keyword">const</span> <span class="identifier">_1</span> <span class="special">=</span> <span class="identifier">argument</span><span class="special"><</span><span class="number">0</span><span class="special">>();</span>
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="number">1</span><span class="special">></span> <span class="special">></span> <span class="keyword">const</span> <span class="identifier">_2</span> <span class="special">=</span> <span class="identifier">argument</span><span class="special"><</span><span class="number">1</span><span class="special">>();</span>
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="number">2</span><span class="special">></span> <span class="special">></span> <span class="keyword">const</span> <span class="identifier">_3</span> <span class="special">=</span> <span class="identifier">argument</span><span class="special"><</span><span class="number">2</span><span class="special">>();</span>
+</pre>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> You can set <tt class="computeroutput"><span class="identifier">PHOENIX_ARG_LIMIT</span></tt>,
+              the predefined maximum placeholder index. By default, <tt class="computeroutput"><span class="identifier">PHOENIX_ARG_LIMIT</span></tt> is set to <tt class="computeroutput"><span class="identifier">PHOENIX_LIMIT</span></tt> (See Actors).</td></tr></tbody>
+</table></div>
+<a name="phoenix.primitives.arguments.user_defined_arguments"></a><h2>
+<a name="id450741"></a>
+        User Defined Arguments
+      </h2>
+<p>
+        When appropriate, you can define your own <tt class="computeroutput"><span class="identifier">argument</span><span class="special"><</span><span class="identifier">N</span><span class="special">></span></tt>
+        names. For example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">argument</span><span class="special"><</span><span class="number">0</span><span class="special">></span> <span class="special">></span> <span class="identifier">x</span><span class="special">;</span> <span class="comment">// note zero based index
+</span></pre>
+<p>
+        <tt class="computeroutput"><span class="identifier">x</span></tt> may now be used as a parameter
+        to a lazy function:
+      </p>
+<pre class="programlisting">
+<span class="identifier">add</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="number">6</span><span class="special">)</span>
+</pre>
+<p>
+        which is equivalent to:
+      </p>
+<pre class="programlisting">
+<span class="identifier">add</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="number">6</span><span class="special">)</span>
+</pre>
+<a name="phoenix.primitives.arguments.evaluating_an_argument"></a><h2>
+<a name="id450940"></a>
+        Evaluating an Argument
+      </h2>
+<p>
+        An argument, when evaluated, selects the Nth argument from the those passed
+        in by the client.
+      </p>
+<p>
+        For example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">char</span>        <span class="identifier">c</span> <span class="special">=</span> <span class="char">'A'</span><span class="special">;</span>
+<span class="keyword">int</span>         <span class="identifier">i</span> <span class="special">=</span> <span class="number">123</span><span class="special">;</span>
+<span class="keyword">const</span> <span class="keyword">char</span><span class="special">*</span> <span class="identifier">s</span> <span class="special">=</span> <span class="string">"Hello World"</span><span class="special">;</span>
+
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">(</span><span class="identifier">c</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>        <span class="comment">//  Get the 1st argument: c
+</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">s</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>     <span class="comment">//  Get the 1st argument: i
+</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg2</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">s</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>     <span class="comment">//  Get the 2nd argument: s
+</span></pre>
+<p>
+        will print out:
+      </p>
+<pre class="programlisting">
+<span class="identifier">A</span>
+<span class="number">123</span>
+<span class="identifier">Hello</span> <span class="identifier">World</span>
+</pre>
+<a name="phoenix.primitives.arguments.extra_arguments"></a><h2>
+<a name="id451295"></a>
+        Extra Arguments
+      </h2>
+<p>
+        In C and C++, a function can have extra arguments that are not at all used
+        by the function body itself. These extra arguments are simply ignored.
+      </p>
+<p>
+        Phoenix also allows extra arguments to be passed. For example, recall our
+        original <tt class="computeroutput"><span class="identifier">add</span></tt> function:
+      </p>
+<pre class="programlisting">
+<span class="identifier">add</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)</span>
+</pre>
+<p>
+        We know now that partially applying this function results to a function that
+        expects 2 arguments. However, the library is a bit more lenient and allows
+        the caller to supply more arguments than is actually required. Thus, <tt class="computeroutput"><span class="identifier">add</span></tt> actually allows 2 <span class="emphasis"><em>or more</em></span>
+        arguments. For instance, with:
+      </p>
+<pre class="programlisting">
+<span class="identifier">add</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">y</span><span class="special">,</span> <span class="identifier">z</span><span class="special">)</span>
+</pre>
+<p>
+        the third argument <tt class="computeroutput"><span class="identifier">z</span></tt> is ignored.
+        Taking this further, in-between arguments are also ignored. Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">add</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg5</span><span class="special">)(</span><span class="identifier">a</span><span class="special">,</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">c</span><span class="special">,</span> <span class="identifier">d</span><span class="special">,</span> <span class="identifier">e</span><span class="special">)</span>
+</pre>
+<p>
+        Here, arguments b, c, and d are ignored. The function <tt class="computeroutput"><span class="identifier">add</span></tt>
+        takes in the first argument (<tt class="computeroutput"><span class="identifier">arg1</span></tt>)
+        and the fifth argument (<tt class="computeroutput"><span class="identifier">arg5</span></tt>).
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> There are a few reasons why enforcing strict arity
+              is not desireable. A case in point is the callback function. Typical
+              callback functions provide more information than is actually needed.
+              Lambda functions are often used as callbacks.</td></tr></tbody>
+</table></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.primitives.values"></a>Values</h3></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">core</span><span class="special">/</span><span class="identifier">value</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Whenever we see a constant in a partially applied function, an
+      </p>
+<pre class="programlisting">
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">value</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">></span> 
+</pre>
+<p>
+        (where T is the type of the constant) is automatically created for us. For
+        instance:
+      </p>
+<pre class="programlisting">
+<span class="identifier">add</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="number">6</span><span class="special">)</span>
+</pre>
+<p>
+        Passing a second argument, <tt class="computeroutput"><span class="number">6</span></tt>,
+        an <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">value</span><span class="special"><</span><span class="keyword">int</span><span class="special">></span> <span class="special">></span></tt> is implicitly created behind the scenes.
+        This is also equivalent to:
+      </p>
+<pre class="programlisting">
+<span class="identifier">add</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">val</span><span class="special">(</span><span class="number">6</span><span class="special">))</span>
+</pre>
+<p>
+        <tt class="computeroutput"><span class="identifier">val</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span></tt> generates
+        an <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">value</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">></span></tt> where <tt class="computeroutput"><span class="identifier">T</span></tt>
+        is the type of <tt class="computeroutput"><span class="identifier">x</span></tt>. In most
+        cases, there's no need to explicitly use <tt class="computeroutput"><span class="identifier">val</span></tt>,
+        but, as we'll see later on, there are situations where this is unavoidable.
+      </p>
+<a name="phoenix.primitives.values.evaluating_a_value"></a><h2>
+<a name="id452041"></a>
+        Evaluating a Value
+      </h2>
+<p>
+        Like arguments, values are also actors. As such, values can be evaluated.
+        Invoking a value gives the value's identity. Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)()</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"Hello World"</span><span class="special">)();</span>
+</pre>
+<p>
+        prints out "3 Hello World".
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.primitives.references"></a>References</h3></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">core</span><span class="special">/</span><span class="identifier">reference</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Values are immutable constants. Attempting to modify a value will result
+        in a compile time error. When we want the function to modify the parameter,
+        we use a reference instead. For instance, imagine a lazy function <tt class="computeroutput"><span class="identifier">add_assign</span></tt>:
+      </p>
+<pre class="programlisting">
+<span class="keyword">void</span> <span class="identifier">add_assign</span><span class="special">(</span><span class="identifier">T</span><span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">T</span> <span class="identifier">y</span><span class="special">)</span> <span class="special">{</span> <span class="identifier">x</span> <span class="special">+=</span> <span class="identifier">y</span><span class="special">;</span> <span class="special">}</span> <span class="comment">// pseudo code
+</span></pre>
+<p>
+        Here, we want the first function argument, x, to be mutable. Obviously, we
+        cannot write:
+      </p>
+<pre class="programlisting">
+<span class="identifier">add_assign</span><span class="special">(</span><span class="number">1</span><span class="special">,</span> <span class="number">2</span><span class="special">)</span> <span class="comment">// error first argument is immutable
+</span></pre>
+<p>
+        In C++, we can pass in a reference to a variable as the first argument in
+        our example above. Yet, by default, the library forces arguments passed to
+        partially applied functions functions to be immutable values (see Values).
+        To achieve our intent, we use:
+      </p>
+<pre class="programlisting">
+<span class="identifier">actor</span><span class="special"><</span><span class="identifier">reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">></span>
+</pre>
+<p>
+        This is similar to <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">value</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">></span></tt> above but instead holds a reference to
+        a variable.
+      </p>
+<p>
+        We normally don't instantiate <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">reference</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">></span></tt> objects directly. Instead we use <tt class="computeroutput"><span class="identifier">ref</span></tt>. For example (where <tt class="computeroutput"><span class="identifier">i</span></tt>
+        is an <tt class="computeroutput"><span class="keyword">int</span></tt> variable):
+      </p>
+<pre class="programlisting">
+<span class="identifier">add_assign</span><span class="special">(</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">i</span><span class="special">),</span> <span class="number">2</span><span class="special">)</span>
+</pre>
+<a name="phoenix.primitives.references.evaluating_a_reference"></a><h2>
+<a name="id452625"></a>
+        Evaluating a Reference
+      </h2>
+<p>
+        References are actors. Hence, references can be evaluated. Such invocation
+        gives the references's identity. Example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span>
+<span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">s</span> <span class="special">=</span> <span class="string">"Hello World"</span><span class="special">;</span>
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">ref</span><span class="special">(</span><span class="identifier">i</span><span class="special">)()</span> <span class="special"><<</span> <span class="identifier">ref</span><span class="special">(</span><span class="identifier">s</span><span class="special">)();</span>
+</pre>
+<p>
+        prints out "3 Hello World"
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.primitives.constant_references"></a>Constant References</h3></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">core</span><span class="special">/</span><span class="identifier">reference</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Another free function <tt class="computeroutput"><span class="identifier">cref</span><span class="special">(</span><span class="identifier">cv</span><span class="special">)</span></tt>
+        may also be used. <tt class="computeroutput"><span class="identifier">cref</span><span class="special">(</span><span class="identifier">cv</span><span class="special">)</span></tt> creates
+        an <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">reference</span><span class="special"><</span><span class="identifier">T</span> <span class="keyword">const</span><span class="special">&></span> <span class="special">></span></tt>
+        object. This is similar to <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">value</span><span class="special"><</span><span class="identifier">T</span><span class="special">></span> <span class="special">></span></tt> but when the data to be passed as argument
+        to a function is heavy and expensive to copy by value, the <tt class="computeroutput"><span class="identifier">cref</span><span class="special">(</span><span class="identifier">cv</span><span class="special">)</span></tt> offers a lighter alternative.
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.primitives.nothing"></a>Nothing</h3></div></div></div>
+<pre class="programlisting">
+<span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">spirit</span><span class="special">/</span><span class="identifier">phoenix</span><span class="special">/</span><span class="identifier">core</span><span class="special">/</span><span class="identifier">nothing</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
+</pre>
+<p>
+        Finally, the <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">null_actor</span><span class="special">></span></tt>
+        does nothing; (a "bum", if you will :-). There's a sole <tt class="computeroutput"><span class="identifier">actor</span><span class="special"><</span><span class="identifier">null_actor</span><span class="special">></span></tt>
+        instance named "nothing". This actor is actually useful in situations
+        where we don't want to do anything. (See <a href="composite.html#phoenix.composite.statement.for__statement" title="for_ Statement">for_
+        Statement</a> for example).
+      </p>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="actors.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="composite.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/references.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/references.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,86 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>References</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="acknowledgement.html" title="Acknowledgement">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="acknowledgement.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.references"></a>References</h2></div></div></div>
+<div class="orderedlist"><ol type="1">
+<li>
+        Why Functional Programming Matters, John Hughes, 1989. Available online at
+        http://www.math.chalmers.se/~rjmh/Papers/whyfp.html.
+      </li>
+<li>
+        Boost.Lambda library, Jaakko Jarvi, 1999-2004 Jaakko Jarvi, Gary Powell.
+        Available online at http://www.boost.org/libs/lambda/.
+      </li>
+<li>
+        Functional Programming in C++ using the FC++ Library: a short article introducing
+        FC++, Brian McNamara and Yannis Smaragdakis, August 2003. Available online
+        at http://www.cc.gatech.edu/~yannis/fc++/.
+      </li>
+<li>
+        Side-effects and partial function application in C++, Jaakko Jarvi and Gary
+        Powell, 2001. Available online at http://osl.iu.edu/~jajarvi/publications/papers/mpool01.pdf.
+      </li>
+<li>
+        Spirit Version 1.8.1, Joel de Guzman, Nov 2004. Available online at http://www.boost.org/libs/spirit/.
+      </li>
+<li>
+        The Boost MPL Library, Aleksey Gurtovoy and David Abrahams, 2002-2004. Available
+        online at http://www.boost.org/libs/mpl/.
+      </li>
+<li>
+        Generic Programming Redesign of Patterns, Proceedings of the 5th European
+        Conference on Pattern Languages of Programs, (EuroPLoP'2000) Irsee, Germany,
+        July 2000. Available online at http://www.coldewey.com/europlop2000/papers/geraud%2Bduret.zip.
+      </li>
+<li>
+        A Gentle Introduction to Haskell, Paul Hudak, John Peterson and Joseph Fasel,
+        1999. Available online at http://www.haskell.org/tutorial/.
+      </li>
+<li>
+        Large scale software design, John Lackos, ISBN 0201633620, Addison-Wesley,
+        July 1996.
+      </li>
+<li>
+        Design Patterns, Elements of Reusable Object-Oriented Software, Erich Gamma,
+        Richard Helm, Ralph Jhonson, and John Vlissides, Addison-Wesley, 1995.
+      </li>
+<li>
+        The Forwarding Problem: Arguments Peter Dimov, Howard E. Hinnant, Dave Abrahams,
+        September 09, 2002. Available online: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm" target="_top">Forwarding
+        Function Problem</a>.
+      </li>
+</ol></div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="acknowledgement.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/starter_kit.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/starter_kit.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,503 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Starter Kit</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="introduction.html" title="Introduction">
+<link rel="next" href="basics.html" title="Basics">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="introduction.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="basics.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.starter_kit"></a>Starter Kit</h2></div></div></div>
+<div class="toc"><dl>
+<dt><span class="section">Values</span></dt>
+<dt><span class="section">References</span></dt>
+<dt><span class="section">Arguments</span></dt>
+<dt><span class="section">Composites</span></dt>
+<dt><span class="section">Lazy Operators</span></dt>
+<dt><span class="section">Lazy Statements</span></dt>
+<dt><span class="section">Construct, New, Delete, Casts</span></dt>
+<dt><span class="section">Lazy Functions</span></dt>
+<dt><span class="section">More</span></dt>
+</dl></div>
+<p>
+      Most "quick starts" only get you a few blocks from where you are.
+      From there, you are on your own. Yet, typically, you'd want to get to the next
+      city. This starter kit shall be as minimal as possible, yet packed as much
+      power as possible.
+    </p>
+<p>
+      So you are busy and always on the go. You do not wish to spend a lot of time
+      studying the library. You wish to be spared the details for later when you
+      need it. For now, all you need to do is to get up to speed as quickly as possible
+      and start using the library. If this is the case, this is the right place to
+      start.
+    </p>
+<p>
+      This chapter is by no means a thorough discourse of the library. For more information
+      on Phoenix, please take some time to read the rest of the User's Guide. Yet,
+      if you just want to use the library quickly, now, this chapter will probably
+      suffice. Rather than taking you to the details of the library, we shall try
+      to provide you with annotated exemplars instead. Hopefully, this will get you
+      into high gear quickly.
+    </p>
+<a name="phoenix.starter_kit.functors_everywhere"></a><h2>
+<a name="id373131"></a>
+      Functors everywhere
+    </h2>
+<p>
+      Phoenix is built on function objects (functors). The functor is the main building
+      block. We compose functors to build more complex functors... to build more
+      complex functors... and so on. Almost everything is a functor.
+    </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> Functors are so ubiquitous in Phoenix that, in the
+            manual, the words <span class="emphasis"><em>"functor"</em></span> and <span class="emphasis"><em>"function"</em></span>
+            are used interchangeably.</td></tr></tbody>
+</table></div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.values"></a>Values</h3></div></div></div>
+<p>
+        Values are functions! Examples:
+      </p>
+<pre class="programlisting">
+<span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)</span>
+<span class="identifier">val</span><span class="special">(</span><span class="string">"Hello, World"</span><span class="special">)</span>
+</pre>
+<p>
+        The first evaluates to a nullary function (a function taking no arguments)
+        that returns an <tt class="computeroutput"><span class="keyword">int</span></tt>, <tt class="computeroutput"><span class="number">3</span></tt>. The second evaluates to a nullary function
+        that returns a <tt class="computeroutput"><span class="keyword">char</span> <span class="keyword">const</span><span class="special">(&)[</span><span class="number">13</span><span class="special">]</span></tt>, <tt class="computeroutput"><span class="string">"Hello,
+        World"</span></tt>.
+      </p>
+<a name="phoenix.starter_kit.values.lazy_evaluation"></a><h2>
+<a name="id373334"></a>
+        Lazy Evaluation
+      </h2>
+<p>
+        Confused? <tt class="computeroutput"><span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)</span></tt> is a unary
+        function, you say? Yes it is. However, read carefully: <span class="emphasis"><em>"evaluates
+        to a nullary function"</em></span>. <tt class="computeroutput"><span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)</span></tt>
+        evaluates to (returns) a nullary function. Aha! <tt class="computeroutput"><span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)</span></tt>
+        returns a function! So, since <tt class="computeroutput"><span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)</span></tt>
+        returns a function, you can invoke it. Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)()</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>
+</pre>
+<p>
+        (See values.cpp)
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Learn more about values here.
+</td></tr></tbody>
+</table></div>
+<p>
+        The second function call (the one with no arguments) calls the nullary function
+        which then returns <tt class="computeroutput"><span class="number">3</span></tt>. The need
+        for a second function call is the reason why the function is said to be
+        <span class="bold"><b><span class="emphasis"><em>Lazily Evaluated</em></span></b></span>. The
+        first call doesn't do anything. You need a second call to finally evaluate
+        the thing. The first call lazily evaluates the function; i.e. doesn't do
+        anything and defers the evaluation for later.
+      </p>
+<a name="phoenix.starter_kit.values.callbacks"></a><h2>
+<a name="id372414"></a>
+        Callbacks
+      </h2>
+<p>
+        It may not be immediately apparent how lazy evaluation can be useful by just
+        looking at the example above. Putting the first and second function call
+        in a single line is really not very useful. However, thinking of <tt class="computeroutput"><span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)</span></tt> as a callback function (and in most cases
+        they are actually used that way), will make it clear. Example:
+      </p>
+<pre class="programlisting">
+<span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">F</span><span class="special">></span>
+<span class="keyword">void</span> <span class="identifier">print</span><span class="special">(</span><span class="identifier">F</span> <span class="identifier">f</span><span class="special">)</span>
+<span class="special">{</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">f</span><span class="special">()</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>
+<span class="special">}</span>
+
+<span class="keyword">int</span>
+<span class="identifier">main</span><span class="special">()</span>
+<span class="special">{</span>
+    <span class="identifier">print</span><span class="special">(</span><span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">));</span>
+    <span class="identifier">print</span><span class="special">(</span><span class="identifier">val</span><span class="special">(</span><span class="string">"Hello World"</span><span class="special">));</span>
+    <span class="keyword">return</span> <span class="number">0</span><span class="special">;</span>
+<span class="special">}</span>
+</pre>
+<p>
+        (See callback.cpp)
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.references"></a>References</h3></div></div></div>
+<p>
+        References are functions. They hold a reference to a value stored somehere.
+        For example, given:
+      </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span>
+<span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">s</span> <span class="special">=</span> <span class="string">"Hello World"</span><span class="special">;</span>
+</pre>
+<p>
+        we create <tt class="computeroutput"><span class="identifier">references</span></tt> to
+        <tt class="computeroutput"><span class="identifier">i</span></tt> and <tt class="computeroutput"><span class="identifier">s</span></tt>
+        this way:
+      </p>
+<pre class="programlisting">
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">i</span><span class="special">)</span>
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">s</span><span class="special">)</span>
+</pre>
+<p>
+        Like <tt class="computeroutput"><span class="identifier">val</span></tt>, the expressions
+        above evaluates to a nullary function; the first one returning an <tt class="computeroutput"><span class="keyword">int</span><span class="special">&</span></tt>,
+        and the second one returning a <tt class="computeroutput"><span class="keyword">char</span> <span class="keyword">const</span><span class="special">*&</span></tt>.
+      </p>
+<p>
+        (See references.cpp)
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Learn more about references here.
+</td></tr></tbody>
+</table></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.arguments"></a>Arguments</h3></div></div></div>
+<p>
+        Arguments are also functions? You bet!
+      </p>
+<p>
+        Until now, we have been dealing with expressions returning a nullary function.
+        Arguments, on the other hand, evaluate to an N-ary function. An argument
+        represents the Nth argument. There are a few predefined arguments arg1, arg2,
+        arg3, arg4 and so on (and it's BLL
+        counterparts: _1, _2, _3, _4 and so on). Examples:
+      </p>
+<pre class="programlisting">
+<span class="identifier">arg1</span> <span class="comment">// one-or-more argument function that returns its first argument
+</span><span class="identifier">arg2</span> <span class="comment">// two-or-more argument function that returns its second argument
+</span><span class="identifier">arg3</span> <span class="comment">// three-or-more argument function that returns its third argument
+</span></pre>
+<p>
+        <tt class="computeroutput"><span class="identifier">argN</span></tt> returns the Nth argument.
+        Examples:
+      </p>
+<pre class="programlisting">
+<span class="keyword">int</span> <span class="identifier">i</span> <span class="special">=</span> <span class="number">3</span><span class="special">;</span>
+<span class="keyword">char</span> <span class="keyword">const</span><span class="special">*</span> <span class="identifier">s</span> <span class="special">=</span> <span class="string">"Hello World"</span><span class="special">;</span>
+<span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span><span class="special">(</span><span class="identifier">i</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>        <span class="comment">// prints 3
+</span><span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg2</span><span class="special">(</span><span class="identifier">i</span><span class="special">,</span> <span class="identifier">s</span><span class="special">)</span> <span class="special"><<</span> <span class="identifier">endl</span><span class="special">;</span>     <span class="comment">// prints "Hello World"
+</span></pre>
+<p>
+        (See arguments.cpp)
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Learn more about arguments here.
+</td></tr></tbody>
+</table></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.composites"></a>Composites</h3></div></div></div>
+<p>
+        What we have seen so far, are what are called <span class="bold"><b>primitives</b></span>.
+        You can think of primitives (such as values, references and arguments) as
+        atoms.
+      </p>
+<p>
+        Things start to get interesting when we start <span class="emphasis"><em>composing</em></span>
+        primitives to form <span class="bold"><b>composites</b></span>. The composites
+        can, in turn, be composed to form even more complex composites.
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.lazy_operators"></a>Lazy Operators</h3></div></div></div>
+<p>
+        You can use the usual set of operators to form composites. Examples:
+      </p>
+<pre class="programlisting">
+<span class="identifier">arg1</span> <span class="special">*</span> <span class="identifier">arg1</span>
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">=</span> <span class="identifier">arg1</span> <span class="special">+</span> <span class="identifier">ref</span><span class="special">(</span><span class="identifier">z</span><span class="special">)</span>
+<span class="identifier">arg1</span> <span class="special">=</span> <span class="identifier">arg2</span> <span class="special">+</span> <span class="special">(</span><span class="number">3</span> <span class="special">*</span> <span class="identifier">arg3</span><span class="special">)</span>
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">=</span> <span class="identifier">arg1</span><span class="special">[</span><span class="identifier">arg2</span><span class="special">]</span> <span class="comment">// assuming arg1 is indexable and arg2 is a valid index
+</span></pre>
+<p>
+        Note the expression: <tt class="computeroutput"><span class="number">3</span> <span class="special">*</span> <span class="identifier">arg3</span></tt>.
+        This expression is actually a short-hand equivalent to: <tt class="computeroutput"><span class="identifier">val</span><span class="special">(</span><span class="number">3</span><span class="special">)</span> <span class="special">*</span> <span class="identifier">arg3</span></tt>.
+        In most cases, like above, you can get away with it. But in some cases, you
+        will have to explicitly wrap your values in <tt class="computeroutput"><span class="identifier">val</span></tt>.
+        Rules of thumb:
+      </p>
+<div class="itemizedlist"><ul type="disc">
+<li>
+          In a binary expression (e.g. <tt class="computeroutput"><span class="number">3</span> <span class="special">*</span> <span class="identifier">arg3</span></tt>),
+          at least one of the operands must be a phoenix primitive or composite.
+        </li>
+<li>
+          In a unary expression (e.g. <tt class="computeroutput"><span class="identifier">arg1</span><span class="special">++</span></tt>), the single operand must be a phoenix
+          primitive or composite.
+        </li>
+</ul></div>
+<p>
+        If these basic rules are not followed, the result is either in error, or
+        is immediately evaluated. Some examples:
+      </p>
+<pre class="programlisting">
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">)</span> <span class="special">=</span> <span class="number">123</span>    <span class="comment">// lazy
+</span><span class="identifier">x</span> <span class="special">=</span> <span class="number">123</span>         <span class="comment">// immediate
+</span>
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">)[</span><span class="number">0</span><span class="special">]</span>       <span class="comment">// lazy
+</span><span class="identifier">x</span><span class="special">[</span><span class="number">0</span><span class="special">]</span>            <span class="comment">// immediate
+</span>
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">)[</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">i</span><span class="special">)]</span>  <span class="comment">// lazy
+</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">)[</span><span class="identifier">i</span><span class="special">]</span>       <span class="comment">// lazy (equivalent to ref(x)[val(i)])
+</span><span class="identifier">x</span><span class="special">[</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">i</span><span class="special">)]</span>       <span class="comment">// illegal (x is not a phoenix primitive or composite)
+</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">x</span><span class="special">[</span><span class="identifier">ref</span><span class="special">(</span><span class="identifier">i</span><span class="special">)])</span>  <span class="comment">// illegal (x is not a phoenix primitive or composite)
+</span></pre>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Learn more about operators here.
+</td></tr></tbody>
+</table></div>
+<a name="phoenix.starter_kit.lazy_operators.first_practical_example"></a><h2>
+<a name="id444445"></a>
+        First Practical Example
+      </h2>
+<p>
+        We've covered enough ground to present a real world example. We want to find
+        the first odd number in an STL container. Normally we use a functor (function
+        object) or a function pointer and pass that in to STL's <tt class="computeroutput"><span class="identifier">find_if</span></tt>
+        generic function:
+      </p>
+<p>
+        Write a function:
+      </p>
+<pre class="programlisting">
+<span class="keyword">bool</span>
+<span class="identifier">is_odd</span><span class="special">(</span><span class="keyword">int</span> <span class="identifier">arg1</span><span class="special">)</span>
+<span class="special">{</span>
+    <span class="keyword">return</span> <span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">;</span>
+<span class="special">}</span>
+</pre>
+<p>
+        Pass a pointer to the function to STL's <tt class="computeroutput"><span class="identifier">find_if</span></tt>
+        algorithm:
+      </p>
+<pre class="programlisting">
+<span class="identifier">find_if</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="special">&</span><span class="identifier">is_odd</span><span class="special">)</span>
+</pre>
+<p>
+        Using Phoenix, the same can be achieved directly with a one-liner:
+      </p>
+<pre class="programlisting">
+<span class="identifier">find_if</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">)</span>
+</pre>
+<p>
+        The expression <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span></tt> automagically
+        creates a functor with the expected behavior. In FP, this unnamed function
+        is called a lambda function. Unlike the function pointer version, which is
+        monomorphic (expects and works only with a fixed type int argument), the
+        Phoenix version is fully polymorphic and works with any container (of ints,
+        of longs, of bignum, etc.) as long as its elements can handle the <tt class="computeroutput"><span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span></tt> expression.
+      </p>
+<p>
+        (See find_if.cpp)
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> ...<span class="bold"><b>That's it, we're done</b></span>.
+              Well if you wish to know a little bit more, read on...</td></tr></tbody>
+</table></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.lazy_statements"></a>Lazy Statements</h3></div></div></div>
+<p>
+        Lazy statements? Sure. There are lazy versions of the C++ statements we all
+        know and love. For example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">if_</span><span class="special">(</span><span class="identifier">arg1</span> <span class="special">></span> <span class="number">5</span><span class="special">)</span>
+    <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span>
+</pre>
+<p>
+        Say, for example, we wish to print all the elements that are greater than
+        5 (separated by a comma) in a vector. Here's how we write it:
+      </p>
+<pre class="programlisting">
+<span class="identifier">for_each</span><span class="special">(</span><span class="identifier">v</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">v</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span>
+    <span class="identifier">if_</span><span class="special">(</span><span class="identifier">arg1</span> <span class="special">></span> <span class="number">5</span><span class="special">)</span>
+    <span class="special">[</span>
+        <span class="identifier">cout</span> <span class="special"><<</span> <span class="identifier">arg1</span> <span class="special"><<</span> <span class="string">", "</span>
+    <span class="special">]</span>
+<span class="special">);</span>
+</pre>
+<p>
+        (See if.cpp)
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Learn more about statements here.
+</td></tr></tbody>
+</table></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.construct__new__delete__casts"></a>Construct, New, Delete, Casts</h3></div></div></div>
+<p>
+        You'll probably want to work with objects. There are lazy versions of constructor
+        calls, <tt class="computeroutput"><span class="keyword">new</span></tt>, <tt class="computeroutput"><span class="keyword">delete</span></tt>
+        and the suite of C++ casts. Examples:
+      </p>
+<pre class="programlisting">
+<span class="identifier">construct</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)</span>  <span class="comment">// constructs a std::string from arg1, arg2
+</span><span class="identifier">new_</span><span class="special"><</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">>(</span><span class="identifier">arg1</span><span class="special">,</span> <span class="identifier">arg2</span><span class="special">)</span>       <span class="comment">// makes a new std::string from arg1, arg2
+</span><span class="identifier">delete_</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">)</span>                       <span class="comment">// deletes arg1 (assumed to be a pointer)
+</span><span class="identifier">static_cast_</span><span class="special"><</span><span class="keyword">int</span><span class="special">*>(</span><span class="identifier">arg1</span><span class="special">)</span>            <span class="comment">// static_cast's arg1 to an int*
+</span></pre>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/note.png" alt="note"></span> Take note that, by convention, names that conflict
+              with C++ reserved words are appended with a single trailing underscore
+              <tt class="computeroutput"><span class="char">'_'</span></tt>
+</td></tr></tbody>
+</table></div>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> Learn more about this here.
+</td></tr></tbody>
+</table></div>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.lazy_functions"></a>Lazy Functions</h3></div></div></div>
+<p>
+        As you write more lambda functions, you'll notice certain patterns that you
+        wish to refactor as reusable functions. When you reach that point, you'll
+        wish that ordinary functions can co-exist with phoenix functions. Unfortunately,
+        the <span class="emphasis"><em>immediate</em></span> nature of plain C++ functions make them
+        incompatible.
+      </p>
+<p>
+        Lazy functions are your friends. The library provides a facility to make
+        lazy functions. The code below is a rewrite of the <tt class="computeroutput"><span class="identifier">is_odd</span></tt>
+        function using the facility:
+      </p>
+<pre class="programlisting">
+<span class="keyword">struct</span> <span class="identifier">is_odd_impl</span>
+<span class="special">{</span>
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Arg</span><span class="special">></span>
+    <span class="keyword">struct</span> <span class="identifier">result</span> 
+    <span class="special">{</span> 
+        <span class="keyword">typedef</span> <span class="keyword">bool</span> <span class="identifier">type</span><span class="special">;</span> 
+    <span class="special">};</span>
+
+    <span class="keyword">template</span> <span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Arg</span><span class="special">></span>
+    <span class="keyword">bool</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Arg</span> <span class="identifier">arg1</span><span class="special">)</span> <span class="keyword">const</span>
+    <span class="special">{</span> 
+        <span class="keyword">return</span> <span class="identifier">arg1</span> <span class="special">%</span> <span class="number">2</span> <span class="special">==</span> <span class="number">1</span><span class="special">;</span> 
+    <span class="special">}</span>
+<span class="special">};</span>
+
+<span class="identifier">function</span><span class="special"><</span><span class="identifier">is_odd_impl</span><span class="special">></span> <span class="identifier">is_odd</span><span class="special">;</span>
+</pre>
+<a name="phoenix.starter_kit.lazy_functions.things_to_note_"></a><h2>
+<a name="id445824"></a>
+        Things to note:
+      </h2>
+<div class="itemizedlist"><ul type="disc">
+<li>
+<tt class="computeroutput"><span class="identifier">result</span></tt> is a nested metafunction
+          that reflects the return type of the function (in this case, bool). This
+          makes the function fully polymorphic: It can work with arbitrary <tt class="computeroutput"><span class="identifier">Arg</span></tt> types.
+        </li>
+<li>
+          There are as many Args in the <tt class="computeroutput"><span class="identifier">result</span></tt>
+          metafunction as in the actual <tt class="computeroutput"><span class="keyword">operator</span><span class="special">()</span></tt>.
+        </li>
+<li>
+<tt class="computeroutput"><span class="identifier">is_odd_impl</span></tt> implements
+          the function.
+        </li>
+<li>
+<tt class="computeroutput"><span class="identifier">is_odd</span></tt>, an instance of
+          <tt class="computeroutput"><span class="identifier">function</span><span class="special"><</span><span class="identifier">is_odd_impl</span><span class="special">></span></tt>,
+          is the lazy function.
+        </li>
+</ul></div>
+<p>
+        Now, <tt class="computeroutput"><span class="identifier">is_odd</span></tt> is a truly lazy
+        function that we can use in conjunction with the rest of phoenix. Example:
+      </p>
+<pre class="programlisting">
+<span class="identifier">find_if</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">begin</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">end</span><span class="special">(),</span> <span class="identifier">is_odd</span><span class="special">(</span><span class="identifier">arg1</span><span class="special">));</span>
+</pre>
+<p>
+        (See function.cpp)
+      </p>
+<a name="phoenix.starter_kit.lazy_functions.predefined_lazy_functions"></a><h2>
+<a name="id446061"></a>
+        Predefined Lazy Functions
+      </h2>
+<p>
+        The library is chock full of STL savvy, predefined lazy functions covering
+        the whole of the STL containers, iterators and algorithms. For example, there
+        are lazy versions of container related operations such as assign, at, back,
+        begin, pop_back, pop_front, push_back, push_front, etc. (See Container).
+      </p>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="phoenix.starter_kit.more"></a>More</h3></div></div></div>
+<p>
+        As mentioned earlier, this chapter is not a thorough discourse of the library.
+        It is meant only to cover enough ground to get you into high gear as quickly
+        as possible. Some advanced stuff is not discussed here (e.g. Scopes);
+        nor are features that provide alternative (short-hand) ways to do the same
+        things (e.g. Bind vs. Lazy
+        Functions).
+      </p>
+<div class="informaltable"><table class="table">
+<colgroup><col></colgroup>
+<tbody><tr><td class="blurb"> <span class="inlinemediaobject"><img src="../images/tip.png" alt="tip"></span> ...<span class="bold"><b>If you still wish to
+              learn more, the read on...</b></span>
+</td></tr></tbody>
+</table></div>
+</div>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="introduction.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="basics.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/html/phoenix/wrap_up.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/html/phoenix/wrap_up.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,72 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>Wrap Up</title>
+<link rel="stylesheet" href="../boostbook.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.66.1">
+<link rel="start" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="up" href="../index.html" title="Chapter 1. Phoenix 2.0">
+<link rel="prev" href="inside_phoenix.html" title="Inside Phoenix">
+<link rel="next" href="acknowledgement.html" title="Acknowledgement">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<table cellpadding="2" width="100%">
+<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
+<td align="center">Home</td>
+<td align="center">Libraries</td>
+<td align="center">People</td>
+<td align="center">FAQ</td>
+<td align="center">More</td>
+</table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="inside_phoenix.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgement.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+<div class="section" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="phoenix.wrap_up"></a>Wrap Up</h2></div></div></div>
+<p>
+      Sooner or later more FP techniques become standard practice as people find
+      the true value of this programming discipline outside the academe and into
+      the mainstream. In as much as structured programming of the 70s and object
+      oriented programming in the 80s and generic programming in the 90s shaped our
+      thoughts towards a more robust sense of software engineering, FP will certainly
+      be a paradigm that will catapult us towards more powerful software design and
+      engineering onward into the new millenium.
+    </p>
+<p>
+      Let me quote Doug Gregor of Boost.org. About functional style programming libraries:
+    </p>
+<div class="blockquote"><blockquote class="blockquote"><p>
+        <span class="emphasis"><em>They're gaining acceptance, but are somewhat stunted by the ubiquitousness
+        of broken compilers. The C++ community is moving deeper into the so-called
+        "STL- style" programming paradigm, which brings many aspects of
+        functional programming into the fold. Look at, for instance, the Spirit parser
+        to see how such function objects can be used to build Yacc-like grammars
+        with semantic actions that can build abstract syntax trees on the fly. This
+        type of functional composition is gaining momentum.</em></span>
+      </p></blockquote></div>
+<p>
+      Indeed. Phoenix is another attempt to introduce more FP techniques into the
+      mainstream. Not only is it a tool that will make life easier for the programmer.
+      In its own right, the actual design of the library itself is a model of true
+      C++ FP in action. The library is designed and structured in a strict but clear
+      and well mannered FP sense. By all means, use the library as a tool. But for
+      those who want to learn more about FP in C++, don't stop there, I invite you
+      to take a closer look at the design of the library itself.
+    </p>
+<p>
+      So there you have it. Have fun! See you in the FP world.
+    </p>
+</div>
+<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
+<td align="left"></td>
+<td align="right"><small>Copyright © 2002-2005 Joel
+      de Guzman, Dan Marsden</small></td>
+</tr></table>
+<hr>
+<div class="spirit-nav">
+<a accesskey="p" href="inside_phoenix.html"><img src="../images/prev.png" alt="Prev"></a><a accesskey="u" href="../index.html"><img src="../images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="acknowledgement.html"><img src="../images/next.png" alt="Next"></a>
+</div>
+</body>
+</html>
Added: trunk/libs/spirit/phoenix/doc/users_manual.qbk
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/doc/users_manual.qbk	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,2769 @@
+[library Phoenix
+    [quickbook 1.3]
+    [version 2.0]
+    [authors [de Guzman, Joel], [Marsden, Dan]]
+    [copyright 2002 2003 2004 2005 Joel de Guzman, Dan Marsden]
+    [category string-text]
+    [purpose Lambda Expressions in C++]
+    [license
+        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])
+    ]
+]
+
+[/ September 2002]
+[/ September 2004]
+[/ September 2005]
+
+[/ Some links]
+
+[def __note__           [$images/note.png]]
+[def __alert__          [$images/alert.png]]
+[def __tip__            [$images/tip.png]]
+
+[def __spirit__         [@http://spirit.sourceforge.net Spirit]]
+[def __haskell__        [@http://www.haskell.org Haskell]]
+[def __mpl__            [@http://www.boost.org/libs/mpl/index.html MPL]]
+[def __bll__            [@http://www.boost.org/libs/lambda/doc/index.html BLL]]
+[def __fcpp__           [@http://www.cc.gatech.edu/~yannis/fc++/ FC++]]
+[def __spirit_repo__    [@http://spirit.sourceforge.net/repository/applications/show_contents.php Spirit Repository]]
+[def __spirit_list__    [@https://lists.sourceforge.net/lists/listinfo/spirit-general Spirit Mailing List]]
+[def __spirit_general__ [@news://news.gmane.org/gmane.comp.spirit.general Spirit General NNTP news portal]]
+[def __gmane__          [@http://www.gmane.org Gmane]]
+[def __mlist_archive__  [@http://news.gmane.org/gmane.comp.parsers.spirit.general]]
+[def __forwarding__     [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm Forwarding Function Problem]]
+[def __boost_mpl__      [@http://boost.org/libs/mpl/doc/index.html Boost.MPL]]
+[def __boost_range__    [@http://boost.org/libs/range/index.html Boost.Range]]
+
+[section Preface]
+
+[:['Functional programming is so called because a program consists entirely of 
+functions. The main program itself is written as a function which receives the 
+program's input as its argument and delivers the program's output as its result. 
+Typically the main function is defined in terms of other functions, which in 
+turn are defined in terms of still more functions until at the bottom level the 
+functions are language primitives.]]
+
+[:*John Hughes*-- /Why Functional Programming Matters/]
+
+[$images/lambda_cpp.png]
+
+[h2 Description]
+
+Phoenix enables Functional Programming (FP) in C++. The design and
+implementation of Phoenix is highly influenced by __fcpp__ by Yannis Smaragdakis
+and Brian McNamara and the __bll__ (Boost Lambda Library) by Jaakko Jaarvi and
+Gary Powell. Phoenix is a blend of FC++ and BLL using the implementation
+techniques used in the __spirit__ inline parser. Phoenix version 2, this
+version, will probably be the last release of the library. Phoenix v2 will be
+the basis of the Phoenix and __bll__ merger.
+
+Phoenix is a header only library. It is extremely modular by design. One can 
+extract and use only a small subset of the full library, literally tearing the 
+library into small pieces, without fear that the pieces won't work anymore. The 
+library is organized in highly independent modules and layers.
+
+[h2 How to use this manual]
+
+The Phoenix library is organized in logical modules. This documentation
+provides a user's guide and reference for each module in the library. A simple
+and clear code example is worth a hundred lines of documentation; therefore, the
+user's guide is presented with abundant examples annotated and explained in
+step-wise manner. The user's guide is based on examples: lots of them.
+
+As much as possible, forward information (i.e. citing a specific piece of
+information that has not yet been discussed) is avoided in the user's manual
+portion of each module. In many cases, though, it is unavoidable that advanced
+but related topics not be interspersed with the normal flow of discussion. To
+alleviate this problem, topics categorized as "advanced" may be skipped at first
+reading.
+
+Some icons are used to mark certain topics indicative of their relevance. These
+icons precede some text to indicate:
+
+[table Icons
+    [[Icon]         [Name]          [Meaning]]
+    [[__note__]     [Note]          [Information provided is auxiliary but will
+                                     give the reader a deeper insight into a specific
+                                     topic. May be skipped.]]
+    [[__alert__]    [Alert]         [Information provided is of utmost importance.]]
+    [[__tip__]      [Tip]           [A potentially useful and helpful piece of
+                                     information.]]
+]
+
+This documentation is automatically generated by Spirit QuickBook documentation
+tool. QuickBook can be found in the __spirit_repo__.
+
+[h2 Support]
+
+Please direct all questions to Spirit's mailing list. You can subscribe to the
+__spirit_list__. The mailing list has a searchable archive. A search link to
+this archive is provided in __spirit__'s home page. You may also read and post
+messages to the mailing list through __spirit_general__ (thanks to __gmane__).
+The news group mirrors the mailing list. Here is a link to the archives:
+__mlist_archive__.
+
+[h2 [*/...To my dear daughter, Phoenix/]]
+
+[endsect]
+
+[section Introduction]
+
+[$images/banner.png]
+
+The Phoenix library enables FP techniques such as higher order functions,
+/lambda/ (unnamed functions), /currying/ (partial function application) and lazy
+evaluation in C++. The focus is more on usefulness and practicality than purity,
+elegance and strict adherence to FP principles.
+
+FP is a programming discipline that is not at all tied to a specific language. 
+FP as a programming discipline can, in fact, be applied to many programming 
+languages. In the realm of C++ for instance, we are seeing more FP techniques 
+being applied. C++ is sufficiently rich to support at least some of the most 
+important facets of FP. C++ is a multiparadigm programming language. It is not 
+only procedural. It is not only object oriented. Beneath the core of the 
+standard C++ library, a closer look into STL gives us a glimpse of FP already in 
+place. It is obvious that the authors of STL know and practice FP. In the near 
+future, we shall surely see more FP trickle down into the mainstream.
+
+The truth is, most of the FP techniques can coexist quite well with the standard
+object oriented and imperative programming paradigms. When we are using STL
+algorithms and functors (function objects) for example, we are already doing FP.
+Phoenix is an evolutionary next step.
+
+[endsect]
+
+[section Starter Kit]
+
+Most "quick starts" only get you a few blocks from where you are. From there, 
+you are on your own. Yet, typically, you'd want to get to the next city. This 
+starter kit shall be as minimal as possible, yet packed as much power as 
+possible.
+
+So you are busy and always on the go. You do not wish to spend a lot of time 
+studying the library. You wish to be spared the details for later when you need 
+it. For now, all you need to do is to get up to speed as quickly as possible and 
+start using the library. If this is the case, this is the right place to start.
+
+This chapter is by no means a thorough discourse of the library. For more 
+information on Phoenix, please take some time to read the rest of the User's 
+Guide. Yet, if you just want to use the library quickly, now, this chapter will 
+probably suffice. Rather than taking you to the details of the library, we shall 
+try to provide you with annotated exemplars instead. Hopefully, this will get 
+you into high gear quickly.
+
+[h2 Functors everywhere]
+
+Phoenix is built on function objects (functors). The functor is the main 
+building block. We compose functors to build more complex functors... to build 
+more complex functors... and so on. Almost everything is a functor. 
+
+[blurb __note__ Functors are so ubiquitous in Phoenix that, in the manual, the 
+words /"functor"/ and /"function"/ are used interchangeably.]
+
+[section Values]
+
+Values are functions! Examples:
+
+    val(3)
+    val("Hello, World")
+
+The first evaluates to a nullary function (a function taking no arguments) that 
+returns an `int`, `3`. The second evaluates to a nullary function that returns 
+a `char const(&)[13]`, `"Hello, World"`. 
+
+[h2 Lazy Evaluation]
+
+Confused? `val(3)` is a unary function, you say? Yes it is. However, read 
+carefully: /"evaluates to a nullary function"/. `val(3)` evaluates to (returns) a 
+nullary function. Aha! `val(3)` returns a function! So, since `val(3)` returns a 
+function, you can invoke it. Example:
+
+    cout << val(3)() << endl;
+
+(See [@../../example/users_manual/values.cpp values.cpp])
+
+[blurb __tip__ Learn more about values [link phoenix.primitives.values here.]]
+
+The second function call (the one with no arguments) calls the nullary function 
+which then returns `3`. The need for a second function call is the reason why 
+the function is said to be [*/Lazily Evaluated/]. The first call doesn't do 
+anything. You need a second call to finally evaluate the thing. The first call 
+lazily evaluates the function; i.e. doesn't do anything and defers the evaluation 
+for later.
+
+[h2 Callbacks]
+
+It may not be immediately apparent how lazy evaluation can be useful by just 
+looking at the example above. Putting the first and second function call in a 
+single line is really not very useful. However, thinking of `val(3)` as a 
+callback function (and in most cases they are actually used that way), will make 
+it clear. Example:
+
+    template <typename F>
+    void print(F f)
+    {
+        cout << f() << endl;
+    }
+    
+    int
+    main()
+    {
+        print(val(3));
+        print(val("Hello World"));
+        return 0;
+    }
+
+(See [@../../example/users_manual/callback.cpp callback.cpp])
+
+[endsect]
+[section References]
+
+References are functions. They hold a reference to a value stored somehere.
+For example, given:
+
+    int i = 3;
+    char const* s = "Hello World";
+
+we create `references` to `i` and `s` this way:
+
+    ref(i)
+    ref(s)
+    
+Like `val`, the expressions above evaluates to a nullary function; the first one 
+returning an `int&`, and the second one returning a `char const*&`.
+
+(See [@../../example/users_manual/references.cpp references.cpp])
+
+[blurb __tip__ Learn more about references [link phoenix.primitives.references here.]]
+
+[endsect]
+[section Arguments]
+
+Arguments are also functions? You bet!
+
+Until now, we have been dealing with expressions returning a nullary function. 
+Arguments, on the other hand, evaluate to an N-ary function. An argument 
+represents the Nth argument. There are a few predefined arguments arg1, 
+arg2, arg3, arg4 and so on (and it's __bll__ counterparts: _1, _2, _3, _4 and so 
+on). Examples:
+
+    arg1 // one-or-more argument function that returns its first argument
+    arg2 // two-or-more argument function that returns its second argument
+    arg3 // three-or-more argument function that returns its third argument
+
+`argN` returns the Nth argument. Examples:
+
+    int i = 3;
+    char const* s = "Hello World";
+    cout << arg1(i) << endl;        // prints 3
+    cout << arg2(i, s) << endl;     // prints "Hello World"
+
+(See [@../../example/users_manual/arguments.cpp arguments.cpp])
+
+[blurb __tip__ Learn more about arguments [link phoenix.primitives.arguments here.]]
+
+[endsect]
+[section Composites]
+
+What we have seen so far, are what are called *primitives*. You can think of 
+primitives (such as values, references and arguments) as atoms.
+
+Things start to get interesting when we start /composing/ primitives to form 
+*composites*. The composites can, in turn, be composed to form even more complex 
+composites.
+
+[endsect]
+[section Lazy Operators]
+
+You can use the usual set of operators to form composites. Examples:
+
+    arg1 * arg1
+    ref(x) = arg1 + ref(z)
+    arg1 = arg2 + (3 * arg3)
+    ref(x) = arg1[arg2] // assuming arg1 is indexable and arg2 is a valid index
+
+Note the expression: `3 * arg3`. This expression is actually a short-hand 
+equivalent to: `val(3) * arg3`. In most cases, like above, you can get away with 
+it. But in some cases, you will have to explicitly wrap your values in `val`. 
+Rules of thumb: 
+
+* In a binary expression (e.g. `3 * arg3`), at least one of the operands must be 
+  a phoenix primitive or composite.
+* In a unary expression (e.g. `arg1++`), the single operand must be a phoenix 
+  primitive or composite.
+  
+If these basic rules are not followed, the result is either in error, or is 
+immediately evaluated. Some examples:
+
+    ref(x) = 123    // lazy
+    x = 123         // immediate
+    
+    ref(x)[0]       // lazy
+    x[0]            // immediate
+    
+    ref(x)[ref(i)]  // lazy
+    ref(x)[i]       // lazy (equivalent to ref(x)[val(i)])
+    x[ref(i)]       // illegal (x is not a phoenix primitive or composite)
+    ref(x[ref(i)])  // illegal (x is not a phoenix primitive or composite)
+
+[blurb __tip__ Learn more about operators [link phoenix.composite.operator here.]]
+
+[h2 First Practical Example]
+
+We've covered enough ground to present a real world example. We want to find the 
+first odd number in an STL container. Normally we use a functor (function 
+object) or a function pointer and pass that in to STL's `find_if` generic 
+function:
+
+Write a function:
+
+    bool
+    is_odd(int arg1)
+    {
+        return arg1 % 2 == 1;
+    }
+
+Pass a pointer to the function to STL's `find_if` algorithm:
+
+    find_if(c.begin(), c.end(), &is_odd)
+
+Using Phoenix, the same can be achieved directly with a one-liner:
+
+    find_if(c.begin(), c.end(), arg1 % 2 == 1)
+
+The expression `arg1 % 2 == 1` automagically creates a functor with the expected 
+behavior. In FP, this unnamed function is called a lambda function. Unlike the 
+function pointer version, which is monomorphic (expects and works only with a 
+fixed type int argument), the Phoenix version is fully polymorphic and works 
+with any container (of ints, of longs, of bignum, etc.) as long as its elements 
+can handle the `arg1 % 2 == 1` expression.
+
+(See [@../../example/users_manual/find_if.cpp find_if.cpp])
+
+[blurb __tip__ ...[*That's it, we're done]. Well if you wish to know a little bit 
+more, read on...]
+
+[endsect]
+[section Lazy Statements]
+
+Lazy statements? Sure. There are lazy versions of the C++ statements we all know 
+and love. For example:
+
+    if_(arg1 > 5)
+        cout << arg1
+
+Say, for example, we wish to print all the elements that are greater than 5 
+(separated by a comma) in a vector. Here's how we write it:
+
+    for_each(v.begin(), v.end(),
+        if_(arg1 > 5)
+        [
+            cout << arg1 << ", "
+        ]
+    );
+
+(See [@../../example/users_manual/if.cpp if.cpp])
+
+[blurb __tip__ Learn more about statements [link phoenix.composite.statement here.]]
+
+[endsect]
+[section Construct, New, Delete, Casts]
+
+You'll probably want to work with objects. There are lazy versions of 
+constructor calls, `new`, `delete` and the suite of C++ casts. Examples:
+
+    construct<std::string>(arg1, arg2)  // constructs a std::string from arg1, arg2
+    new_<std::string>(arg1, arg2)       // makes a new std::string from arg1, arg2
+    delete_(arg1)                       // deletes arg1 (assumed to be a pointer)
+    static_cast_<int*>(arg1)            // static_cast's arg1 to an int*
+
+[blurb __note__ Take note that, by convention, names that conflict with C++ 
+reserved words are appended with a single trailing underscore `'_'`]
+
+[blurb __tip__ Learn more about this [link phoenix.composite.object here.]]
+
+[endsect]
+[section Lazy Functions]
+
+As you write more lambda functions, you'll notice certain patterns that you wish 
+to refactor as reusable functions. When you reach that point, you'll wish that 
+ordinary functions can co-exist with phoenix functions. Unfortunately, the 
+/immediate/ nature of plain C++ functions make them incompatible.
+
+Lazy functions are your friends. The library provides a facility to make lazy 
+functions. The code below is a rewrite of the `is_odd` function using the 
+facility:
+
+    struct is_odd_impl
+    {
+        template <typename Arg>
+        struct result 
+        { 
+            typedef bool type; 
+        };
+    
+        template <typename Arg>
+        bool operator()(Arg arg1) const
+        { 
+            return arg1 % 2 == 1; 
+        }
+    };
+    
+    function<is_odd_impl> is_odd;
+
+[h2 Things to note:]
+
+* `result` is a nested metafunction that reflects the return type of the 
+  function (in this case, bool). This makes the function fully polymorphic:
+  It can work with arbitrary `Arg` types.
+* There are as many Args in the `result` metafunction as in the actual 
+  `operator()`.
+* `is_odd_impl` implements the function.
+* `is_odd`, an instance of `function<is_odd_impl>`, is the lazy function.
+
+Now, `is_odd` is a truly lazy function that we can use in conjunction with the 
+rest of phoenix. Example:
+
+    find_if(c.begin(), c.end(), is_odd(arg1));
+
+(See [@../../example/users_manual/function.cpp function.cpp])
+
+[h2 Predefined Lazy Functions]
+
+The library is chock full of STL savvy, predefined lazy functions covering the 
+whole of the STL containers, iterators and algorithms. For example, there are lazy 
+versions of container related operations such as assign, at, back, begin, 
+pop_back, pop_front, push_back, push_front, etc. (See [link phoenix.container 
+Container]).
+
+[endsect]
+[section More]
+
+As mentioned earlier, this chapter is not a thorough discourse of the library. 
+It is meant only to cover enough ground to get you into high gear as quickly as 
+possible. Some advanced stuff is not discussed here (e.g. [link phoenix.composite.scope 
+Scopes]); nor are features that provide alternative (short-hand) ways to do the 
+same things (e.g. [link phoenix.composite.bind Bind] vs. Lazy Functions).
+
+[blurb __tip__ ...*If you still wish to learn more, the read on...*]
+
+[endsect]
+[endsect]
+
+[section Basics]
+
+[def __constant_n__ /n/]
+[def __argument_n__ a/n/]
+
+Almost everything is a function in the Phoenix library that can be evaluated as 
+`f(a1, a2, ..., __argument_n__)`, where __constant_n__ is the function's arity, or number of arguments that the 
+function expects. Operators are also functions. For example, `a + b` is just a 
+function with arity == 2 (or binary). `a + b` is the same as `add(a, b)`, `a + b 
++ c` is the same as `add(add(a, b), c)`.
+
+[blurb __note__ Amusingly, functions may even return functions. We shall see
+what this means in a short while.]
+
+[h2 Partial Function Application]
+
+Think of a function as a black box. You pass arguments and it returns something 
+back. The figure below depicts the typical scenario.
+
+[$images/fbox.png]
+
+A fully evaluated function is one in which all the arguments are given. All 
+functions in plain C++ are fully evaluated. When you call the `sin(x)` function, 
+you have to pass a number x. The function will return a result in return: the 
+sin of x. When you call the `add(x, y)` function, you have to pass two numbers x 
+and y. The function will return the sum of the two numbers. The figure below is 
+a fully evaluated `add` function.
+
+[$images/adder.png]
+
+A partially applied function, on the other hand, is one in which not all the 
+arguments are supplied. If we are able to partially apply the function `add` 
+above, we may pass only the first argument. In doing so, the function does not 
+have all the required information it needs to perform its task to compute and 
+return a result. What it returns instead is another function, a lambda function 
+--another black box. Unlike the original `add` function which has an arity of 2, 
+the resulting lambda function has an arity of 1. Why? because we already 
+supplied part of the input: `2`
+
+[$images/add2.png]
+
+Now, when we shove in a number into our lambda function, it will return 2 plus
+whatever we pass in. The lambda function essentially remembers 1) the original
+function, `add`, and 2) the partial input, 2. The figure below illustrates a
+case where we pass 3 to our lambda function, which then returns 5:
+
+[$images/add2_call.png]
+
+Obviously, partially applying the `add` function, as we see above, cannot be 
+done directly in C++ where we are expected to supply all the arguments that a 
+function expects. That's where the Phoenix library comes in. The library 
+provides the facilities to do partial function application.
+
+[h2 STL and higher order functions]
+
+So, what's all the fuss? What makes partial function application so useful? 
+Recall our original example in the [link phoenix.starter_kit previous section]:
+
+    find_if(c.begin(), c.end(), arg1 % 2 == 1)
+
+The expression `arg1 % 2 == 1` evaluates to a lambda function. `arg1` is a placeholder
+for an argument to be supplied later. Hence, since there's only one unsupplied argument, the
+lambda function has an arity 1. It just so happens that `find_if` supplies the
+unsupplied argument as it loops from `c.begin()` to `c.end()`.
+
+[blurb __note__ Higher order functions are functions which can take other
+functions as arguments, and may also return functions as results. Higher order
+functions are functions that are treated like any other objects and can be used as
+arguments and return values from functions.]
+
+[h2 Lazy Evaluation]
+
+In Phoenix, to put it more accurately, function evaluation has two stages:
+
+# Partial application
+# Final evaluation
+
+The first stage is handled by a set of generator functions. These are your front 
+ends (in the client's perspective). These generators create (through partial 
+function application), higher order functions that can be passed on just like 
+any other function pointer or function object. The second stage, the actual 
+function call, can be invoked or executed anytime in the future, or not at all; 
+hence /"lazy"/.
+
+If we look more closely, the first step involves partial function application:
+
+    arg1 % 2 == 1
+
+The second step is the actual function invocation (done inside the `find_if`
+function. These are the back-ends (often, the final invocation is never actually
+seen by the client). In our example, the `find_if`, if we take a look inside,
+we'll see something like:
+
+    template <class InputIterator, class Predicate>
+    InputIterator
+    find_if(InputIterator first, InputIterator last, Predicate pred)
+    {
+        while (first != last && !pred(*first))  // <--- The lambda function is called here
+            ++first;                            //      passing in *first
+        return first;
+    }
+
+Again, typically, we, as clients, see only the first step. However, in this 
+document and in the examples and tests provided, don't be surprised to see the 
+first and second steps juxtaposed in order to illustrate the complete semantics
+of Phoenix expressions. Examples:
+
+    int x = 1;
+    int y = 2;
+
+    cout << (arg1 % 2 == 1)(x) << endl; // prints 1 or true
+    cout << (arg1 % 2 == 1)(y) << endl; // prints 0 or false
+
+
+[h2 Forwarding Function Problem]
+
+Usually, we, as clients, write the call-back functions while libraries (such as 
+STL) provide the callee (e.g. `find_if`). In case the role is reversed, e.g. 
+if you have to write an STL algorithm that takes in a predicate, or develop a 
+GUI library that accepts event handlers, you have to be aware of a little known 
+problem in C++ called the "__forwarding__". 
+
+Look again at the code above:
+
+    (arg1 % 2 == 1)(x)
+
+Notice that, in the second-stage (the final evaluation), we used a variable `x`. 
+Be aware that the second stage cannot accept non-const temporaries and literal 
+constants. Hence, this will fail:
+
+    (arg1 % 2 == 1)(123) // Error!
+
+Disallowing non-const rvalues partially solves the "__forwarding__" but 
+prohibits code like above.
+
+[h2 Polymorphic Functions]
+
+Unless otherwise noted, Phoenix generated functions are fully polymorphic. For
+instance, the `add` example above can apply to integers, floating points, user
+defined complex numbers or even strings. Example:
+
+    std::string h("Hello");
+    char const* w = " World";
+    std::string r = add(arg1, arg2)(h, w);
+
+evaluates to `std::string("Hello World")`. The observant reader might notice 
+that this function call in fact takes in heterogeneous arguments where `arg1` is 
+of type `std::string` and `arg2` is of type `char const*`. `add` still works 
+because the C++ standard library allows the expression `a + b` where `a` is a 
+`std::string` and `b` is a `char const*`.
+
+[endsect]
+
+[section Organization]
+
+Care and attention to detail was given, painstakingly, to the design and
+implementation of Phoenix. 
+
+The library is organized in four layers:
+
+[$images/organization.png]
+
+The modules are orthogonal, with no cyclic dependencies. 
+Lower layers do not depend on higher layers. Modules in a layer do not depend on other modules in the same layer.
+This means, for example, that Bind can be completely discarded if it is
+not required; or one could perhaps take out Operator and Statement and just use Function,
+which may be desireable in a pure FP application.
+
+The library has grown from the original Phoenix but still comprises only 
+header files. There are no object files to link against. 
+
+[h2 Core]
+
+The lowest two layers comprise the core.
+
+The `Actor` is the main concept behind the library. Lazy functions are 
+abstracted as actors. There are only 2 
+kinds of actors:
+
+# Primitives
+# Composites
+
+Primitives provide the basic building blocks of functionality within Phoenix.
+Composites are used to combine these primitives together to provide more
+powerful functionality.
+
+Composites are composed of zero or more actors. Each actor in a composite can
+again be another composite.
+
+[table Modules
+    [[Module]           [Description]]
+    [[Function]         [Lazy functions support (e.g. `add`)]]
+    [[Operator]         [Lazy operators support (e.g. `+`)]]
+    [[Statement]        [Lazy statments (e.g. `if_`, `while_`)]]
+    [[Object]           [Lazy casts (e.g. `static_cast_`), 
+                        object creation destruction (e.g.
+                        `new_`, `delete_`)]]
+    [[Scope]            [Support for scopes, local variables and lambda-lambda]]
+    [[Bind]             [Lazy functions from free functions, member functions or member variables.]]
+    [[Container]        [Set of predefined "lazy" functions that work on STL
+                        containers and sequences (e.g. `push_back`).]]
+    [[Algorithm]        [Set of predefined "lazy" versions of the STL algorithms
+                        (e.g. `find_if`).]]
+]
+
+Each module is defined in a header file with the same name. For example,
+the core module is defined in `<boost/spirit/phoenix/core.hpp>`.
+
+[table Includes
+    [[Module]           [File]]
+    [[Core]             [`#include <boost/spirit/phoenix/core.hpp>`]]
+    [[Function]         [`#include <boost/spirit/phoenix/function.hpp>`]]
+    [[Operator]         [`#include <boost/spirit/phoenix/operator.hpp>`]]
+    [[Statement]        [`#include <boost/spirit/phoenix/statement.hpp>`]]
+    [[Object]           [`#include <boost/spirit/phoenix/object.hpp>`]]
+    [[Scope]            [`#include <boost/spirit/phoenix/scope.hpp>`]]
+    [[Bind]             [`#include <boost/spirit/phoenix/bind.hpp>`]]
+    [[Container]        [`#include <boost/spirit/phoenix/container.hpp>`]]
+    [[Algorithm]        [`#include <boost/spirit/phoenix/algorithm.hpp>`]]
+]
+
+[blurb __tip__ Finer grained include files are available per feature; see the 
+succeeding sections.]
+
+[endsect]
+
+[section Actors]
+
+The `Actor` is the main concept behind the library. Actors are function objects. 
+An actor can accept 0 to `PHOENIX_LIMIT` arguments.
+
+[blurb __note__ You can set `PHOENIX_LIMIT`, the predefined maximum arity an
+actor can take. By default, `PHOENIX_LIMIT` is set to 10.]
+
+Phoenix supplies an `actor` class template whose specializations
+model the `Actor` concept.  `actor` has one template parameter, `Eval`,
+that supplies the smarts to evaluate the resulting function.
+
+    template <typename Eval>
+    struct actor : Eval
+    {
+        return_type
+        operator()() const;
+
+        template <typename T0>
+        return_type
+        operator()(T0& _0) const;
+
+        template <typename T0, typename T1>
+        return_type
+        operator()(T0& _0, T1& _1) const;
+
+        //...
+    };
+
+The actor class accepts the arguments through a set of function call operators 
+for 0 to `PHOENIX_LIMIT` arities (Don't worry about the details, for now. Note, for example, 
+that we skimp over the details regarding `return_type`). The arguments 
+are then forwarded to the actor's `Eval` for evaluation. 
+
+[endsect]
+
+[section Primitives]
+
+Actors are composed to create more complex actors in a tree-like hierarchy. The
+primitives are atomic entities that are like the leaves in the tree. Phoenix is
+extensible. New primitives can be added anytime. Right out of the box, there are
+only a few primitives. This section shall deal with these preset primitives.
+
+[section Arguments]
+
+    #include <boost/spirit/phoenix/core/argument.hpp>
+
+We use an instance of:
+
+    actor<argument<N> >
+
+to represent the Nth function argument. The argument placeholder acts as an 
+imaginary data-bin where a function argument will be placed.
+
+[h2 Predefined Arguments]
+
+There are a few predefined instances of `actor<argument<N> >` named 
+`arg1`..`argN`, and its __bll__ counterpart `_1`..`_N`. (where N is a predefined 
+maximum).
+
+Here are some sample preset definitions of `arg1`..`argN`
+
+    actor<argument<0> > const arg1 = argument<0>();
+    actor<argument<1> > const arg2 = argument<1>();
+    actor<argument<2> > const arg3 = argument<2>();
+
+and its __bll__ `_1`..`_N` style counterparts:
+
+    actor<argument<0> > const _1 = argument<0>();
+    actor<argument<1> > const _2 = argument<1>();
+    actor<argument<2> > const _3 = argument<2>();
+
+[blurb __note__ You can set `PHOENIX_ARG_LIMIT`, the predefined maximum
+placeholder index. By default, `PHOENIX_ARG_LIMIT` is set to `PHOENIX_LIMIT`
+(See [link phoenix.actors Actors]).]
+
+[h2 User Defined Arguments]
+
+When appropriate, you can define your own `argument<N>` names. For example:
+
+    actor<argument<0> > x; // note zero based index
+
+`x` may now be used as a parameter to a lazy function:
+
+    add(x, 6)
+
+which is equivalent to:
+
+    add(arg1, 6)
+
+[h2 Evaluating an Argument]
+
+An argument, when evaluated, selects the Nth argument from the those passed
+in by the client.
+
+For example:
+
+    char        c = 'A';
+    int         i = 123;
+    const char* s = "Hello World";
+
+    cout << arg1(c) << endl;        //  Get the 1st argument: c
+    cout << arg1(i, s) << endl;     //  Get the 1st argument: i
+    cout << arg2(i, s) << endl;     //  Get the 2nd argument: s
+
+will print out:
+
+    A
+    123
+    Hello World
+
+[h2 Extra Arguments]
+
+In C and C++, a function can have extra arguments that are not at all used by
+the function body itself. These extra arguments are simply ignored.
+
+Phoenix also allows extra arguments to be passed. For example, recall our
+original `add` function:
+
+    add(arg1, arg2)
+
+We know now that partially applying this function results to a function that 
+expects 2 arguments. However, the library is a bit more lenient and allows the 
+caller to supply more arguments than is actually required. Thus, `add` actually 
+allows 2 /or more/ arguments. For instance, with:
+
+    add(arg1, arg2)(x, y, z)
+
+the third argument `z` is ignored. Taking this further, in-between arguments are
+also ignored. Example:
+
+    add(arg1, arg5)(a, b, c, d, e)
+
+Here, arguments b, c, and d are ignored. The function `add` takes in the first
+argument (`arg1`) and the fifth argument (`arg5`).
+
+[blurb __note__ There are a few reasons why enforcing strict arity is not
+desireable. A case in point is the callback function. Typical callback functions
+provide more information than is actually needed. Lambda functions are often
+used as callbacks.]
+
+[endsect]
+
+[section Values]
+
+    #include <boost/spirit/phoenix/core/value.hpp>
+
+Whenever we see a constant in a partially applied function, an
+
+    actor<value<T> > 
+
+(where T is the type of the constant) is automatically created for 
+us. For instance:
+
+    add(arg1, 6)
+
+Passing a second argument, `6`, an `actor<value<int> >` is implicitly created 
+behind the scenes. This is also equivalent to:
+
+    add(arg1, val(6))
+
+`val(x)` generates an `actor<value<T> >` where `T` is the type of `x`. In most 
+cases, there's no need to explicitly use `val`, but, as we'll see later on,
+there are situations where this is unavoidable.
+
+[h2 Evaluating a Value]
+
+Like arguments, values are also actors. As such, values can be evaluated. 
+Invoking a value gives the value's identity. Example:
+
+    cout << val(3)() << val("Hello World")();
+
+prints out "3 Hello World".
+
+[endsect]
+
+[section References]
+
+    #include <boost/spirit/phoenix/core/reference.hpp>
+
+Values are immutable constants. Attempting to modify a value will result in a 
+compile time error. When we want the function to modify the parameter, we use a 
+reference instead. For instance, imagine a lazy function `add_assign`:
+
+    void add_assign(T& x, T y) { x += y; } // pseudo code
+
+Here, we want the first function argument, x, to be mutable. Obviously, we
+cannot write:
+
+    add_assign(1, 2) // error first argument is immutable
+
+In C++, we can pass in a reference to a variable as the first argument in our 
+example above. Yet, by default, the library forces arguments passed to partially 
+applied functions functions to be immutable values (see [link phoenix.primitives.values 
+Values]). To achieve our intent, we use:
+
+    actor<reference<T> >
+    
+This is similar to `actor<value<T> >` above but instead holds a reference to a 
+variable.
+
+We normally don't instantiate `actor<reference<T> >` objects directly. Instead we 
+use `ref`. For example (where `i` is an `int` variable):
+
+    add_assign(ref(i), 2)
+
+[h2 Evaluating a Reference]
+
+References are actors. Hence, references can be evaluated. Such invocation gives 
+the references's identity. Example:
+
+    int i = 3;
+    char const* s = "Hello World";
+    cout << ref(i)() << ref(s)();
+
+prints out "3 Hello World"
+
+[endsect]
+[section Constant References]
+
+    #include <boost/spirit/phoenix/core/reference.hpp>
+
+Another free function `cref(cv)` may also be used. `cref(cv)` creates an 
+`actor<reference<T const&> >` object. This is similar to `actor<value<T> >` but 
+when the data to be passed as argument to a function is heavy and expensive to 
+copy by value, the `cref(cv)` offers a lighter alternative.
+
+[endsect]
+[section Nothing]
+
+    #include <boost/spirit/phoenix/core/nothing.hpp>
+
+Finally, the `actor<null_actor>` does nothing; (a "bum", if you will :-). 
+There's a sole `actor<null_actor>` instance named "nothing". This actor is 
+actually useful in situations where we don't want to do anything. (See 
+[link phoenix.composite.statement.for__statement for_ Statement] for example).
+
+[endsect]
+
+[endsect]
+
+[section Composite]
+
+Actors may be combined in a multitude of ways to form composites. Composites are 
+actors that are composed of zero or more actors. Composition is hierarchical. An 
+element of the composite can be a primitive or again another composite. The 
+flexibility to arbitrarily compose hierarchical structures allows us to form 
+intricate constructions that model complex functions, statements and 
+expressions.
+
+A composite is-a tuple of 0..N actors. N is the predefined maximum actors a 
+composite can take.
+
+[blurb __note__ You can set `PHOENIX_COMPOSITE_LIMIT`, the predefined maximum
+actors a composite can take. By default, `PHOENIX_COMPOSITE_LIMIT` is set to
+`PHOENIX_LIMIT` (See [link phoenix.actors Actors]).]
+
+As mentioned, each of the actors A0..AN can, in turn, be another composite, 
+since a composite is itself an actor. This makes the composite a recursive 
+structure. The actual evaluation is handled by a composite specific eval policy. 
+
+[section Function]
+
+    #include <boost/spirit/phoenix/function/function.hpp>
+
+The `function` class template provides a mechanism for implementing lazily
+evaluated functions. Syntactically, a lazy function looks like an ordinary C/C++ function.
+The function call looks familiar and feels the same as ordinary C++ functions.
+However, unlike ordinary functions, the actual function execution is deferred.
+
+Unlike ordinary function pointers or functor objects that need to be explicitly bound through the bind function (see [link phoenix.composite.bind Bind]), 
+the argument types of these functions are automatically lazily bound.
+
+In order to create a lazy function, we need to implement a model of the 
+FunctionEval concept. For a function that takes `N` arguments, a model of FunctionEval must
+provide:
+
+* An `operator()` that implements that takes `N` arguments, and implements
+the function logic.
+* A nested metafunction `result<A1, ... AN>` that takes the types of the `N` arguments to
+the function and returns the result type of the function. (There is a special case for function 
+objects that accept no arguments. Such nullary functors are only required to define a typedef 
+`result_type` that reflects the return type of its `operator()`).
+
+For example, the following type implements the FunctionEval concept, in order to provide a
+lazy factorial function:
+
+    struct factorial_impl
+    {
+        template <typename Arg>
+        struct result
+        {
+            typedef Arg type;
+        };
+
+        template <typename Arg>
+        Arg operator()(Arg n) const
+        {
+            return (n <= 0) ? 1 : n * this->operator()(n-1);
+        }
+    };
+
+(See [@../../example/users_manual/factorial.cpp factorial.cpp])
+
+Having implemented the `factorial_impl` type, we can declare and instantiate a lazy 
+`factorial` function this way:
+
+    function<factorial_impl> factorial;
+
+Invoking a lazy function such as `factorial` does not immediately execute the function
+object `factorial_impl`. Instead, an [link phoenix.actors actor] object is
+created and returned to the caller. Example:
+
+    factorial(arg1)
+
+does nothing more than return an actor. A second function call will invoke
+the actual factorial function. Example:
+
+    int i = 4;
+    cout << factorial(arg1)(i);
+
+will print out "24".
+
+Take note that in certain cases (e.g. for function objects with state), an
+instance of the model of FunctionEval may be passed on to the constructor. Example:
+
+    function<factorial_impl> factorial(ftor);
+
+where ftor is an instance of factorial_impl (this is not necessary in this case 
+as `factorial_impl` does not require any state). 
+
+[blurb __alert__ Take care though when using function objects with state because they are
+often copied repeatedly, and state may change in one of the copies, rather than the
+original.]
+
+[endsect]
+
+[section Operator]
+
+This facility provides a mechanism for lazily evaluating operators.
+Syntactically, a lazy operator looks and feels like an ordinary C/C++ infix,
+prefix or postfix operator. The operator application looks the same. However,
+unlike ordinary operators, the actual operator execution is deferred. Samples:
+
+    arg1 + arg2
+    1 + arg1 * arg2
+    1 / -arg1
+    arg1 < 150
+
+We have seen the lazy operators in action (see [link phoenix.starter_kit 
+Quick Start]). Let's go back and examine them a little bit further:
+
+    find_if(c.begin(), c.end(), arg1 % 2 == 1)
+
+Through operator overloading, the expression `arg1 % 2 == 1` actually generates
+an actor. This actor object is passed on to STL's `find_if` function. From
+the viewpoint of STL, the composite is simply a function object expecting a
+single argument of the containers value_type. For each element in `c`,
+the element is passed on as an argument `arg1` to the actor (function
+object). The actor checks if this is an odd value based on the expression
+`arg1 % 2 == 1` where arg1 is replaced by the container's element.
+
+Like lazy functions (see
+[link phoenix.composite.function function]), lazy operators are not immediately executed
+when invoked. Instead, an actor (see [link phoenix.actors actors])
+object is created and returned to the caller. Example:
+
+    (arg1 + arg2) * arg3
+
+does nothing more than return an actor. A second function call will evaluate
+the actual operators. Example:
+
+    int i = 4, j = 5, k = 6;
+    cout << ((arg1 + arg2) * arg3)(i, j, k);
+
+will print out "54".
+
+Operator expressions are lazily evaluated following four simple rules:
+
+# A binary operator, except `->*` will be lazily evaluated when 
+  /at least/ one of its operands is an actor object 
+  (see [link phoenix.actors actors]).
+# Unary operators are lazily evaluted if their argument is an actor object.
+# Operator `->*` is lazily evaluted if the left hand argument is an actor object.
+# The result of a lazy operator is an actor object that can in turn allow the
+  applications of rules 1 and 2.
+
+For example, to check the following expression is lazily evaluated:
+
+    -(arg1 + 3 + 6)
+
+# Following rule 1, `arg1 + 3` is lazily evaluated since `arg1` is an actor
+  (see [link phoenix.primitives primitives]).
+# The result of this `arg1 + 3` expression is an actor object, following rule 4.
+# Continuing, `arg1 + 3 + 6` is again lazily evaluated.
+  Rule 2.
+# By rule 4 again, the result of  `arg1 + 3 + 6` is an actor object.
+# As `arg1 + 3 + 6` is an actor, `-(arg1 + 3 + 6)` is lazily evaluated. Rule 2.
+
+Lazy-operator application is highly contagious. In most cases, a single `argN`
+actor infects all its immediate neighbors within a group (first level or
+parenthesized expression).
+
+Note that at least one operand of any operator must be a valid actor
+for lazy evaluation to take effect.  To force lazy evaluation of an
+ordinary expression, we can use `ref(x)`, `val(x)` or `cref(x)` to
+transform an operand into a valid actor object (see [link phoenix.primitives primitives].  
+For example:
+
+     1 << 3;      // Immediately evaluated
+     val(1) << 3; // Lazily evaluated
+
+[h2 Supported operators]
+
+[h3 Unary operators]
+
+    prefix:   ~, !, -, +, ++, --, & (reference), * (dereference)
+    postfix:  ++, --
+
+[h3 Binary operators]
+
+    =, [], +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
+    +, -, *, /, %, &, |, ^, <<, >>
+    ==, !=, <, >, <=, >=
+    &&, ||, ->*
+
+[h3 Ternary operator]
+
+    if_else(c, a, b)
+
+The ternary operator deserves special mention. Since C++ does not allow us to 
+overload the conditional expression: `c ? a : b`, the if_else pseudo function is 
+provided for this purpose. The behavior is identical, albeit in a lazy manner.
+
+[h3 Member pointer operator]
+
+    a->*member_object_pointer
+    a->*member_function_pointer
+
+The left hand side of the member pointer operator must be an actor returning a pointer
+type. The right hand side of the member pointer operator may be either a pointer to member
+object or pointer to member function.
+
+If the right hand side is a member object pointer, the result is an actor which, when evaluated,
+returns a reference to that member. For example:
+
+    struct A
+    {
+        int member;
+    };
+
+    A* a = new A;
+    ...
+
+    (arg1->*&A::member)(a); // returns member a->member
+
+If the right hand side is a member function pointer, the result is an actor which, when invoked, calls the specified member function. For example:
+
+    struct A
+    {
+        int func(int);
+    };
+
+    A* a = new A;
+    int i = 0;
+
+    (arg1->*&A::func)(arg2)(a, i); // returns a->func(i)
+
+[table Include Files
+    [[Operators]                    [File]]
+    [[`-`, `+`, `++`, `--`, `+=`, 
+      `-=`, `*=`, `/=`, `%=`, 
+      `*`, `/`, `%`]                [`#include <boost/spirit/phoenix/operator/arithmetic.hpp>`]]
+    [[`&=`, `|=`, `^=`, `<<=`, 
+      `>>=`, `&`, `|`, `^`, `<<`, 
+      `>>`]                         [`#include <boost/spirit/phoenix/operator/bitwise.hpp>`]]
+    [[`==`, `!=`, `<`, 
+      `<=`, `>`, `>=`]              [`#include <boost/spirit/phoenix/operator/comparison.hpp>`]]
+    [[`<<`, `>>`]                   [`#include <boost/spirit/phoenix/operator/io.hpp>`]]
+    [[`!`, &&, `||`]                [`#include <boost/spirit/phoenix/operator/logical.hpp>`]]
+    [[`&x`, `*p`, `=`, `[]`]        [`#include <boost/spirit/phoenix/operator/self.hpp>`]]
+    [[`if_else(c, a, b)`]           [`#include <boost/spirit/phoenix/operator/if_else.hpp>`]]
+    [[`->*`]                        [`#include <boost/spirit/phoenix/operator/member.hpp>`]]
+]
+
+[endsect]
+
+[section Statement]
+
+[*/Lazy statements.../]
+
+The primitives and composite building blocks presented so far are sufficiently 
+powerful to construct quite elaborate structures. We have presented lazy-
+functions and lazy-operators. How about lazy-statements? First, an appetizer:
+
+Print all odd-numbered contents of an STL container using `std::for_each` 
+([@../../example/users_manual/all_odds.cpp all_odds.cpp]):
+
+    for_each(c.begin(), c.end(),
+        if_(arg1 % 2 == 1)
+        [
+            cout << arg1 << ' '
+        ]
+    );
+
+Huh? Is that valid C++? Read on...
+
+Yes, it is valid C++. The sample code above is as close as you can get to the 
+syntax of C++. This stylized C++ syntax differs from actual C++ code. First, the 
+`if` has a trailing underscore. Second, the block uses square brackets instead 
+of the familiar curly braces {}.
+
+[blurb __note__ *C++ in C++?*\n\n
+    In as much as __spirit__ attempts to mimic EBNF in C++, 
+    Phoenix attempts to mimic C++ in C++!!!
+]
+
+Here are more examples with annotations. The code almost speaks for itself.
+
+[section Block Statement]
+
+    #include <boost/spirit/phoenix/statement/sequence.hpp>
+
+Syntax:
+
+    statement,
+    statement,
+    ....
+    statement
+
+Basically, these are comma separated statements. Take note that unlike the C/C++ 
+semicolon, the comma is a separator put *in-between* statements. This is like 
+Pascal's semicolon separator, rather than C/C++'s semicolon terminator. For 
+example:
+
+    statement,
+    statement,
+    statement, // ERROR!
+
+Is an error. The last statement should not have a comma. Block statements can be 
+grouped using the parentheses. Again, the last statement in a group should not 
+have a trailing comma.
+
+    statement,
+    statement,
+    (
+        statement,
+        statement
+    ),
+    statement
+
+Outside the square brackets, block statements should be grouped. For example:
+
+    for_each(c.begin(), c.end(),
+        (
+            do_this(arg1),
+            do_that(arg1)
+        )
+    );
+
+Wrapping a comma operator chain around a parentheses pair blocks the
+interpretation as an argument separator.  The reason for the exception for
+the square bracket operator is that the operator always takes exactly one
+argument, so it "transforms" any attempt at multiple arguments with a comma
+operator chain (and spits out an error for zero arguments).
+
+[endsect]
+[section if_ Statement]
+
+    #include <boost/spirit/phoenix/statement/if.hpp>
+
+We have seen the `if_` statement. The syntax is:
+
+    if_(conditional_expression)
+    [
+        sequenced_statements
+    ]
+
+[endsect]
+[section if_else_ statement]
+
+    #include <boost/spirit/phoenix/statement/if.hpp>
+
+The syntax is
+
+    if_(conditional_expression)
+    [
+        sequenced_statements
+    ]
+    .else_
+    [
+        sequenced_statements
+    ]
+
+Take note that `else` has a leading dot and a trailing underscore: `.else_`
+
+Example: This code prints out all the elements and appends `" > 5"`, `" == 5"` 
+or `" < 5"` depending on the element's actual value:
+
+    for_each(c.begin(), c.end(),
+        if_(arg1 > 5)
+        [
+            cout << arg1 << " > 5\n"
+        ]
+        .else_
+        [
+            if_(arg1 == 5)
+            [
+                cout << arg1 << " == 5\n"
+            ]
+            .else_
+            [
+                cout << arg1 << " < 5\n"
+            ]
+        ]
+    );
+
+Notice how the `if_else_` statement is nested.
+
+[endsect]
+[section switch_ statement]
+
+    #include <boost/spirit/phoenix/statement/switch.hpp>
+
+The syntax is:
+
+    switch_(integral_expression)
+    [
+        case_<integral_value>(sequenced_statements),
+        ...
+        default_<integral_value>(sequenced_statements)
+    ]
+
+A comma separated list of cases, and an optional default can be provided. Note unlike
+a normal switch statement, cases do not fall through.
+
+Example: This code prints out `"one"`, `"two"` or `"other value"` depending on the
+element's actual value:
+
+    for_each(c.begin(), c.end(),
+        switch_(arg1)
+        [
+            case_<1>(cout << val("one") << '\n'),
+            case_<2>(cout << val("two") << '\n'),
+            default_(cout << val("other value") << '\n')
+        ]
+    );
+
+[endsect]
+[section while_ Statement]
+
+    #include <boost/spirit/phoenix/statement/while.hpp>
+
+The syntax is:
+
+    while_(conditional_expression)
+    [
+        sequenced_statements
+    ]
+
+Example: This code decrements each element until it reaches zero and prints out 
+the number at each step. A newline terminates the printout of each value.
+
+    for_each(c.begin(), c.end(),
+        (
+            while_(arg1--)
+            [
+                cout << arg1 << ", "
+            ],
+            cout << val("\n")
+        )
+    );
+
+[endsect]
+[section do_while_ Statement]
+
+    #include <boost/spirit/phoenix/statement/do_while.hpp>
+
+The syntax is:
+
+    do_
+    [
+        sequenced_statements
+    ]
+    .while_(conditional_expression)
+
+Again, take note that `while` has a leading dot and a trailing underscore: 
+`.while_`
+
+Example: This code is almost the same as the previous example above with a 
+slight twist in logic.
+
+    for_each(c.begin(), c.end(),
+        (
+            do_
+            [
+                cout << arg1 << ", "
+            ]
+            .while_(arg1--),
+            cout << val("\n")
+        )
+    );
+
+[endsect]
+[section for_ Statement]
+
+    #include <boost/spirit/phoenix/statement/for.hpp>
+
+The syntax is:
+
+    for_(init_statement, conditional_expression, step_statement)
+    [
+        sequenced_statements
+    ]
+
+It is again very similar to the C++ for statement. Take note that the 
+init_statement, conditional_expression and step_statement are separated by the 
+comma instead of the semi-colon and each must be present (i.e. `for_(,,)` is 
+invalid). This is a case where the [link phoenix.primitives.nothing nothing] 
+actor can be useful.
+
+Example: This code prints each element N times where N is the element's value. A 
+newline terminates the printout of each value.
+
+    int iii;
+    for_each(c.begin(), c.end(),
+        (
+            for_(ref(iii) = 0, ref(iii) < arg1, ++ref(iii))
+            [
+                cout << arg1 << ", "
+            ],
+            cout << val("\n")
+        )
+    );
+
+As before, all these are lazily evaluated. The result of such statements are in 
+fact composites that are passed on to STL's for_each function. In the viewpoint 
+of `for_each`, what was passed is just a functor, no more, no less.
+
+[blurb __note__ Unlike lazy functions and lazy operators, lazy statements always 
+return void.]
+
+[endsect]
+[section try_ catch_ Statement]
+
+    #include <boost/spirit/phoenix/statement/try_catch.hpp>
+
+The syntax is:
+
+    try_
+    [
+        sequenced_statements
+    ]
+    .catch_<exception_type>()
+    [
+        sequenced_statements
+    ]
+    ...
+    .catch_all
+    [
+        sequenced_statement
+    ]
+
+Note the usual underscore after try and catch, and the extra parentheses required 
+after the catch.
+
+Example: The following code calls the (lazy) function `f` for each element, and
+prints messages about different exception types it catches.
+
+    try_
+    [
+        f(arg1)
+    ]
+    .catch_<runtime_error>()
+    [
+        cout << val("caught runtime error or derived\n")
+    ]
+    .catch_<exception>()
+    [
+        cout << val("caught exception or derived\n")
+    ]
+    .catch_all
+    [
+        cout << val("caught some other type of exception\n")
+    ]
+
+[endsect]
+[section throw_]
+
+    #include <boost/spirit/phoenix/statement/throw.hpp>
+
+As a natural companion to the try/catch support, the statement module provides
+lazy throwing and rethrowing of exceptions.
+
+The syntax to throw an exception is:
+
+    throw_(exception_expression)
+
+The syntax to rethrow an exception is:
+
+    throw_()
+
+Example: This code extends the try/catch example, rethrowing exceptions derived from
+runtime_error or exception, and translating other exception types to runtime_errors.
+
+    try_
+    [
+        f(arg1)
+    ]
+    .catch_<runtime_error>()
+    [
+        cout << val("caught runtime error or derived\n"),
+        throw_()
+    ]
+    .catch_<exception>()
+    [
+        cout << val("caught exception or derived\n"),
+        throw_()
+    ]
+    .catch_all
+    [
+        cout << val("caught some other type of exception\n"),
+        throw_(runtime_error("translated exception"))
+    ]
+
+[endsect]
+[endsect]
+
+[section Object]
+
+The Object module deals with object construction, destruction and conversion. 
+The module provides /"lazy"/ versions of C++'s object constructor, `new`, 
+`delete`, `static_cast`, `dynamic_cast`, `const_cast` and `reinterpret_cast`.
+
+[h2 Construction]
+
+[*/Lazy constructors.../]
+
+    #include <boost/spirit/phoenix/object/construct.hpp>
+
+Lazily construct an object from an arbitrary set of arguments:
+
+    construct<T>(ctor_arg1, ctor_arg2, ..., ctor_argN);
+
+where the given parameters are the parameters to the contructor of the object of 
+type T (This implies, that type T is expected to have a constructor with a 
+corresponding set of parameter types.).
+
+Example:
+
+    construct<std::string>(arg1, arg2)
+
+Constructs a `std::string` from `arg1` and `arg2`.
+
+[blurb __note__ The maximum number of actual parameters is limited by the 
+preprocessor constant PHOENIX_COMPOSITE_LIMIT. Note though, that this limit 
+should not be greater than PHOENIX_LIMIT. By default, `PHOENIX_COMPOSITE_LIMIT` 
+is set to `PHOENIX_LIMIT` (See [link phoenix.actors Actors]).]
+
+[h2 New]
+
+[*/Lazy new.../]
+
+    #include <boost/spirit/phoenix/object/new.hpp>
+
+Lazily construct an object, on the heap, from an arbitrary set of arguments:
+
+    new_<T>(ctor_arg1, ctor_arg2, ..., ctor_argN);
+
+where the given parameters are the parameters to the contructor of the object of 
+type T (This implies, that type T is expected to have a constructor with a 
+corresponding set of parameter types.).
+
+Example:
+
+    new_<std::string>(arg1, arg2) // note the spelling of new_ (with trailing underscore)
+
+Creates a `std::string` from `arg1` and `arg2` on the heap.
+
+[blurb __note__ Again, the maximum number of actual parameters is limited by the 
+preprocessor constant PHOENIX_COMPOSITE_LIMIT. See the note above.]
+
+[h2 Delete]
+
+[*/Lazy delete.../]
+
+    #include <boost/spirit/phoenix/object/delete.hpp>
+
+Lazily delete an object, from the heap:
+
+    delete_(arg);
+
+where arg is assumed to be a pointer to an object.
+
+Example:
+
+    delete_<std::string>(arg1) // note the spelling of delete_ (with trailing underscore)
+
+[h2 Casts]
+
+[*/Lazy casts.../]
+
+    #include <boost/spirit/phoenix/object/static_cast.hpp>
+    #include <boost/spirit/phoenix/object/dynamic_cast.hpp>
+    #include <boost/spirit/phoenix/object/const_cast.hpp>
+    #include <boost/spirit/phoenix/object/reinterpret_cast.hpp>
+
+The set of lazy C++ cast template functions provide a way of lazily casting an 
+object of a certain type to another type. The syntax resembles the well known 
+C++ casts. Take note however that the lazy versions have a trailing underscore.
+
+    static_cast_<T>(lambda_expression)
+    dynamic_cast_<T>(lambda_expression)
+    const_cast_<T>(lambda_expression)
+    reinterpret_cast_<T>(lambda_expression)
+
+Example:
+
+    static_cast_<Base*>(&arg1)
+
+Static-casts the address of `arg1` to a `Base*`.
+
+[endsect]
+
+[section Scope]
+
+Up until now, the most basic ingredient is missing: creation of and access to 
+local variables in the stack. When recursion comes into play, you will soon 
+realize the need to have true local variables. It may seem that we do not need 
+this at all since an unnamed lambda function cannot call itself anyway; at least 
+not directly. With some sort of arrangement, situations will arise where a 
+lambda function becomes recursive. A typical situation occurs when we store a 
+lambda function in a [@http://www.boost.org/libs/function Boost.Function], 
+essentially naming the unnamed lambda.
+
+There will also be situations where a lambda function gets passed as an argument 
+to another function. This is a more common situation. In this case, the lambda 
+function assumes a new scope; new arguments and possibly new local variables.
+
+This section deals with local variables and nested lambda scopes.
+
+[h2 Local Variables]
+
+    #include <boost/spirit/phoenix/scope/local_variable.hpp>
+
+We use an instance of:
+
+    actor<local_variable<Key> >
+
+to represent a local variable. The local variable acts as an imaginary data-bin 
+where a local, stack based data will be placed. `Key` is an arbitrary type that 
+is used to identify the local variable. Example:
+
+    struct size_key;
+    actor<local_variable<size_key> > size;
+
+[h2 Predefined Local Variables]
+
+There are a few predefined instances of `actor<local_variable<Key> >` 
+named `_a`..`_z` that you can already use. To make use of them, simply use the 
+`namespace boost::phoenix::local_names`:
+
+    using namespace boost::phoenix::local_names;
+
+[h2 let]
+
+    #include <boost/spirit/phoenix/scope/let.hpp>
+
+You declare local variables using the syntax:
+
+    let(local-declarations)
+    [
+        let-body
+    ]
+
+`let` allows 1..N local variable declarations (where N == 
+`PHOENIX_LOCAL_LIMIT`). Each declaration follows the form:
+
+    local-id = lambda-expression
+
+[blurb __note__ You can set `PHOENIX_LOCAL_LIMIT`, the predefined maximum local 
+variable declarations in a let expression. By default, `PHOENIX_LOCAL_LIMIT` is 
+set to `PHOENIX_LIMIT`.]
+
+Example:
+
+    let(_a = 123, _b = 456)
+    [
+        _a + _b
+    ]
+
+[h2 Reference Preservation]
+
+The type of the local variable assumes the type of the lambda- expression. Type 
+deduction is reference preserving. For example:
+
+    let(_a = arg1, _b = 456)
+
+`_a` assumes the type of `arg1`: a reference to an argument, while `_b` has type 
+`int`. 
+
+Consider this:
+
+    int i = 1;
+    
+    let(_a = arg1)
+    [
+        cout << --_a << ' '
+    ]
+    (i);
+
+    cout << i << endl;
+
+the output of above is : 0 0 
+
+While with this:
+
+    int i = 1;
+    
+    let(_a = val(arg1))
+    [
+        cout << --_a << ' '
+    ]
+    (i);
+
+    cout << i << endl;
+
+the output is : 0 1 
+
+Reference preservation is necessary because we need to have L-value access to 
+outer lambda-scopes (especially the arguments). `arg`s and `ref`s are L-values. 
+`val`s are R-values.
+
+[h2 Visibility]
+
+The scope and lifetimes of the local variables is limited within the let-body. 
+`let` blocks can be nested. A local variable may hide an outer local variable. 
+For example:
+
+    let(_x = 1, _y = ", World")
+    [
+        // _x here is an int: 1
+
+        let(_x = "Hello") // hides the outer _x
+        [
+            cout << _x << _y // prints "Hello, World"
+        ]
+    ]
+
+The RHS (right hand side lambda-expression) of each local-declaration cannot 
+refer to any LHS local-id. At this point, the local-ids are not in scope yet; 
+they will only be in scope in the let-body. The code below is in error:
+
+    let(
+        _a = 1
+      , _b = _a // Error: _a is not in scope yet
+    )
+    [
+        // _a and _b's scope starts here
+        /*. body .*/
+    ]
+
+However, if an outer let scope is available, this will be searched. Since
+the scope of the RHS of a local-declaration is the outer scope enclosing
+the let, the RHS of a local-declaration can refer to a local variable of
+an outer scope:
+
+    let(_a = 1)
+    [
+        let(
+            _a = 1
+          , _b = _a // Ok. _a refers to the outer _a
+        )
+        [
+            /*. body .*/
+        ]
+    ]
+
+[h2 lambda]
+
+    #include <boost/spirit/phoenix/scope/lambda.hpp>
+
+A lot of times, you'd want to write a lazy function that accepts one or more 
+functions (higher order functions). STL algorithms come to mind, for example. 
+Consider a lazy version of `stl::for_each`:
+
+    struct for_each_impl
+    {
+        template <typename C, typename F>
+        struct result
+        {
+            typedef void type;
+        };
+
+        template <typename C, typename F>
+        void operator()(C& c, F f) const
+        {
+            std::for_each(c.begin(), c.end(), f);
+        }
+    };
+
+    function<for_each_impl> const for_each = for_each_impl();
+
+Notice that the function accepts another function, `f` as an argument. The scope 
+of this function, `f`, is limited within the `operator()`. When `f` is called 
+inside `std::for_each`, it exists in a new scope, along with new arguments and, 
+possibly, local variables. This new scope is not at all related to the outer 
+scopes beyond the `operator()`. 
+
+Simple syntax:
+
+    lambda
+    [
+        lambda-body
+    ]
+
+Like `let`, local variables may be declared, allowing 1..N local variable 
+declarations (where N == `PHOENIX_LOCAL_LIMIT`):
+
+    lambda(local-declarations)
+    [
+        lambda-body
+    ]
+
+The same restrictions apply with regard to scope and visibility. The RHS 
+(right hand side lambda-expression) of each local-declaration cannot refer 
+to any LHS local-id. The local-ids are not in scope yet; they will be in 
+scope only in the lambda-body:
+
+    lambda(
+        _a = 1
+      , _b = _a // Error: _a is not in scope yet
+    )
+
+See [link phoenix.composite.scope.visibility `let` Visibility] above for more information.
+
+Example: Using our lazy `for_each` let's print all the elements in a container:
+
+    for_each(arg1, lambda[cout << arg1])
+
+As far as the arguments are concerned (arg1..argN), the scope in which the 
+lambda-body exists is totally new. The left `arg1` refers to the argument passed 
+to `for_each` (a container). The right `arg1` refers to the argument passed by 
+`std::for_each` when we finally get to call `operator()` in our `for_each_impl` 
+above (a container element).
+
+Yet, we may wish to get information from outer scopes. While we do not have 
+access to arguments in outer scopes, what we still have is access to local 
+variables from outer scopes. We may only be able to pass argument related 
+information from outer `lambda` scopes through the local variables. 
+
+[blurb __note__ This is a crucial difference between `let` and `lambda`: `let` 
+does not introduce new arguments; `lambda` does.]
+
+Another example: Using our lazy `for_each`, and a lazy `push_back`:
+
+    struct push_back_impl
+    {
+        template <typename C, typename T>
+        struct result
+        {
+            typedef void type;
+        };
+
+        template <typename C, typename T>
+        void operator()(C& c, T& x) const
+        {
+            c.push_back(x);
+        }
+    };
+
+    function<push_back_impl> const push_back = push_back_impl();
+
+write a lambda expression that accepts:
+
+# a 2-dimensional container (e.g. `vector<vector<int> >`)
+# a container element (e.g. `int`)
+
+and pushes-back the element to each of the `vector<int>`.
+
+Solution:
+
+    for_each(arg1, 
+        lambda(_a = arg2)
+        [
+            push_back(arg1, _a)
+        ]
+    )
+
+Since we do not have access to the arguments of the outer scopes beyond the 
+lambda-body, we introduce a local variable `_a` that captures the second outer 
+argument: `arg2`. Hence: _a = arg2. This local variable is visible inside the 
+lambda scope.
+
+(See [@../../example/users_manual/lambda.cpp lambda.cpp])
+
+[endsect]
+
+[section Bind]
+
+['Binding] is the act of tying together a function to some arguments for 
+deferred (lazy) evaluation. Named [link phoenix.composite.function Lazy functions] 
+require a bit of typing. Unlike (unnamed) lambda expressions, we need to write a 
+functor somewhere offline, detached from the call site. If you wish to transform a 
+plain function, member function or member variable to a lambda expression, `bind` 
+is your friend. 
+
+[blurb __note__ Take note that binders are monomorphic. Rather than binding 
+functions, the preferred way is to write true generic and polymorphic [link 
+phoenix.composite.function lazy-functions]. However, since most of the time we 
+are dealing with adaptation of exisiting code, binders get the job done faster.]
+
+There is a set of overloaded `bind` template functions. Each `bind(x)` 
+function generates a suitable binder object, a [link phoenix.composite 
+composite].
+
+[h2 Binding Functions]
+
+    #include <boost/spirit/phoenix/bind/bind_function.hpp>
+
+Example, given a function `foo`:
+
+    void foo(int n) 
+    { 
+        std::cout << n << std::endl; 
+    }
+
+Here's how the function `foo` may be bound:
+
+    bind(&foo, arg1)
+
+This is now a full-fledged [link phoenix.composite composite] that can finally 
+be evaluated by another function call invocation. A second function call will 
+invoke the actual `foo` function. Example:
+
+    int i = 4;
+    bind(&foo, arg1)(i);
+
+will print out "4".
+
+[h2 Binding Member Functions]
+
+    #include <boost/spirit/phoenix/bind/bind_member_function.hpp>
+
+Binding member functions can be done similarly. A bound member function takes in 
+a pointer or reference to an object as the first argument. For instance, given:
+
+    struct xyz 
+    { 
+        void foo(int) const; 
+    };
+
+`xyz`'s `foo` member function can be bound as:
+
+    bind(&xyz::foo, obj, arg1) // obj is an xyz object
+
+Take note that a lazy-member functions expects the first argument to be a 
+pointer or reference to an object. Both the object (reference or pointer) and 
+the arguments can be lazily bound. Examples:
+
+    xyz obj;
+    bind(&xyz::foo, arg1, arg2)     // arg1.foo(arg2)
+    bind(&xyz::foo, obj, arg1)      // obj.foo(arg1)
+    bind(&xyz::foo, obj, 100)       // obj.foo(100)
+
+[h2 Binding Member Variables]
+
+    #include <boost/spirit/phoenix/bind/bind_member_variable.hpp>
+
+Member variables can also be bound much like member functions. Member variables 
+are not functions. Yet, like the [link phoenix.primitives.references `ref(x)`] that 
+acts like a nullary function returning a reference to the data, member variables, 
+when bound, act like a unary function, taking in a pointer or reference to an 
+object as its argument and returning a reference to the bound member variable. 
+For instance, given:
+
+    struct xyz 
+    { 
+        int v; 
+    };
+
+`xyz::v` can be bound as:
+
+    bind(&xyz::v, obj) // obj is an xyz object
+
+As noted, just like the bound member function, a bound member variable also 
+expects the first (and only) argument to be a pointer or reference to an object. 
+The object (reference or pointer) can be lazily bound. Examples:
+
+    xyz obj;
+    bind(&xyz::v, arg1)             // arg1.v 
+    bind(&xyz::v, obj)              // obj.v  
+    bind(&xyz::v, arg1)(obj) = 4    // obj.v = 4
+
+[endsect]
+
+[endsect]
+[section Container]
+
+    #include <boost/spirit/phoenix/container.hpp>
+
+The container module predefines a set of lazy functions that work on STL 
+containers. These functions provide a mechanism for the lazy evaluation of the 
+public member functions of the STL containers. The lazy functions are thin 
+wrappers that simply forward to their respective counterparts in the STL 
+library. 
+
+Lazy functions are provided for all of the member functions of the following 
+containers:
+
+* deque
+* list
+* map
+* multimap
+* vector
+
+Indeed, should your class have member functions with the same names and 
+signatures as those listed below, then it will automatically be supported. To 
+summarize, lazy functions are provided for member functions:
+
+* assign
+* at
+* back
+* begin
+* capacity
+* clear
+* empty
+* end
+* erase
+* front
+* get_allocator
+* insert
+* key_comp
+* max_size
+* pop_back
+* pop_front
+* push_back
+* push_front
+* rbegin
+* rend
+* reserve
+* resize
+* size
+* splice
+* value_comp
+
+The lazy functions' names are the same as the corresponding member function. The 
+difference is that the lazy functions are free functions and therefore does not 
+use the member "dot" syntax.
+
+[table Sample usage
+    [["Normal" version]                 ["Lazy" version]]
+    [[`my_vector.at(5)`]                [`at(arg1, 5)`]]
+    [[`my_list.size()`]                 [`size(arg1)`]]
+    [[`my_vector1.swap(my_vector2)`]    [`swap(arg1, arg2)`]]
+]
+
+Notice that member functions with names that clash with stl algorithms are 
+absent. This will be provided in Phoenix's algorithm module.
+
+No support is provided here for lazy versions of `operator+=`, `operator[]` etc. 
+Such operators are not specific to STL containers and lazy versions can 
+therefore be found in [link phoenix.composite.operator operators].
+
+The following table describes the container functions and their semantics.
+
+[blurb __tip__ Arguments in brackets denote optional parameters.]
+
+[table Lazy STL Container Functions
+    [[Function]                         [Semantics]]
+    [[`assign(c, a[, b, c])`]           [`c.assign(a[, b, c])`]]
+    [[`at(c, i)`]                       [`c.at(i)`]]
+    [[`back(c)`]                        [`c.back()`]]
+    [[`begin(c)`]                       [`c.begin()`]]
+    [[`capacity(c)`]                    [`c.capacity()`]]
+    [[`clear(c)`]                       [`c.clear()`]]
+    [[`empty(c)`]                       [`c.empty()`]]
+    [[`end(c)`]                         [`c.end()`]]
+    [[`erase(c, a[, b])`]               [`c.erase(a[, b])`]]
+    [[`front(c)`]                       [`c.front()`]]
+    [[`get_allocator(c)`]               [`c.get_allocator()`]]
+    [[`insert(c, a[, b, c])`]           [`c.insert(a[, b, c])`]]
+    [[`key_comp(c)`]                    [`c.key_comp()`]]
+    [[`max_size(c)`]                    [`c.max_size()`]]
+    [[`pop_back(c)`]                    [`c.pop_back()`]]
+    [[`pop_front(c)`]                   [`c.pop_front()`]]
+    [[`push_back(c, d)`]                [`c.push_back(d)`]]
+    [[`push_front(c, d)`]               [`c.push_front(d)`]]
+    [[`pop_front(c)`]                   [`c.pop_front()`]]
+    [[`rbegin(c)`]                      [`c.rbegin()`]]
+    [[`rend(c)`]                        [`c.rend()`]]
+    [[`reserve(c, n)`]                  [`c.reserve(n)`]]
+    [[`resize(c, a[, b])`]              [`c.resize(a[, b])`]]
+    [[`size(c)`]                        [`c.size()`]]
+    [[`splice(c, a[, b, c, d])`]        [`c.splice(a[, b, c, d])`]]
+    [[`value_comp(c)`]                  [`c.value_comp()`]]
+]
+
+[endsect]
+
+[section Algorithm]
+
+    #include <boost/spirit/phoenix/algorithm.hpp>
+
+The algorithm module provides wrappers for the standard algorithms in the 
+`<algorithm>` and `<numeric>` headers.
+
+The algorithms are divided into the categories iteration, transformation and querying,
+modelling the __boost_mpl__ library. The different algorithm classes can be
+included using the headers:
+
+    #include <boost/spirit/phoenix/stl/algorithm/iteration.hpp>
+    #include <boost/spirit/phoenix/stl/algorithm/transformation.hpp>
+    #include <boost/spirit/phoenix/stl/algorithm/querying.hpp>
+
+The functions of the algorithm module take ranges as arguments where 
+appropriate. This is different to the standard 
+library, but easy enough to pick up. Ranges are described in detail in the 
+__boost_range__ library.
+
+For example, using the standard copy algorithm to copy between 2 arrays:
+
+    int array[] = {1, 2, 3};
+    int output[3];
+    std::copy(array, array + 3, output); // We have to provide iterators 
+                                         // to both the start and end of array
+
+The analogous code using the phoenix algorithm module is:
+
+    int array[] = {1, 2, 3};
+    int output[3];
+    copy(arg1, arg2)(array, output); // Notice only 2 arguments, the end of 
+                                     // array is established automatically
+
+The __boost_range__ library provides support for standard containers, strings and 
+arrays, and can be extended to support additional types.
+
+The following tables describe the different categories of algorithms, and their
+semantics.
+
+[blurb __tip__ Arguments in brackets denote optional parameters.]
+
+[table Iteration Algorithms
+    [[Function]                         [stl Semantics]]
+    [[`for_each(r, c)`]                 [`for_each(begin(r), end(r), f)`]]
+    [[`accumulate(r, o[, f])`]          [`accumulate(begin(r), end(r), o[, f])`]]
+]
+
+[table Querying Algorithms
+    [[Function]                         [stl Semantics]]
+    [[`find(r, a)`]                     [`find(begin(r), end(r), a)`]]
+    [[`find_if(r, f)`]                  [`find_if(begin(r), end(r), f)`]]
+    [[`find_end(r1, r2[, f])`]          [`find_end(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`find_first_of(r1, r2[, f])`]     [`find_first_of(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`adjacent_find(r[, f])`]          [`adjacent_find(begin(r), end(r)[, f])`]]
+    [[`count(r, a)`]                    [`count(begin(r), end(r), a)`]]
+    [[`count_if(r, f)`]                 [`count_if(begin(r), end(r), f)`]]
+    [[`distance(r)`]                    [`distance(begin(r), end(r))`]]
+    [[`mismatch(r, i[, f])`]            [`mismatch(begin(r), end(r), i[, f])`]]
+    [[`equal(r, i[, f])`]               [`equal(begin(r), end(r), i[, f])`]]
+    [[`search(r1, r2[, f])`]            [`search(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`lower_bound(r, a[, f])`]         [`lower_bound(begin(r), end(r), a[, f])`]]
+    [[`upper_bound(r, a[, f])`]         [`upper_bound(begin(r), end(r), a[, f])`]]
+    [[`equal_range(r, a[, f])`]         [`equal_range(begin(r), end(r), a[, f])`]]
+    [[`binary_search(r, a[, f])`]       [`binary_search(begin(r), end(r), a[, f])`]]
+    [[`includes(r1, r2[, f])`]          [`includes(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`min_element(r[, f])`]            [`min_element(begin(r), end(r)[, f])`]]
+    [[`max_element(r[, f])`]            [`max_element(begin(r), end(r)[, f])`]]
+    [[`lexicographical_compare(r1, r2[, f])`]   [`lexicographical_compare(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+]
+
+[table Transformation Algorithms
+    [[Function]                         [stl Semantics]]
+    [[`copy(r, o)`]                     [`copy(begin(r), end(r), o)`]]
+    [[`copy_backward(r, o)`]            [`copy_backward(begin(r), end(r), o)`]]
+    [[`transform(r, o, f)`]             [`transform(begin(r), end(r), o, f)`]]
+    [[`transform(r, i, o, f)`]          [`transform(begin(r), end(r), i, o, f)`]]
+    [[`replace(r, a, b)`]               [`replace(begin(r), end(r), a, b)`]]
+    [[`replace_if(r, f, a)`]            [`replace(begin(r), end(r), f, a)`]]
+    [[`replace_copy(r, o, a, b)`]       [`replace_copy(begin(r), end(r), o, a, b)`]]
+    [[`replace_copy_if(r, o, f, a)`]    [`replace_copy_if(begin(r), end(r), o, f, a)`]]
+    [[`fill(r, a)`]                     [`fill(begin(r), end(r), a)`]]
+    [[`fill_n(r, n, a)`]                [`fill_n(begin(r), n, a)`]]
+    [[`generate(r, f)`]                 [`generate(begin(r), end(r), f)`]]
+    [[`generate_n(r, n, f)`]            [`generate_n(begin(r), n, f)`]]
+    [[`remove(r, a)`]                   [`remove(begin(r), end(r), a)`]]
+    [[`remove_if(r, f)`]                [`remove_if(begin(r), end(r), f)`]]
+    [[`remove_copy(r, o, a)`]           [`remove_copy(begin(r), end(r), o, a)`]]
+    [[`remove_copy_if(r, o, f)`]        [`remove_copy_if(begin(r), end(r), o, f)`]]
+    [[`unique(r[, f])`]                 [`unique(begin(r), end(r)[, f])`]]
+    [[`unique_copy(r, o[, f])`]         [`unique_copy(begin(r), end(r), o[, f])`]]
+    [[`reverse(r)`]                     [`reverse(begin(r), end(r))`]]
+    [[`reverse_copy(r, o)`]             [`reverse_copy(begin(r), end(r), o)`]]
+    [[`rotate(r, m)`]                   [`rotate(begin(r), m, end(r))`]]
+    [[`rotate_copy(r, m, o)`]           [`rotate_copy(begin(r), m, end(r), o)`]]
+    [[`random_shuffle(r[, f])`]         [`random_shuffle(begin(r), end(r), f)`]]
+    [[`partition(r, f)`]                [`partition(begin(r), end(r), f)`]]
+    [[`stable_partition(r, f)`]         [`stable_partition(begin(r), end(r), f)`]]
+    [[`sort(r[, f])`]                   [`sort(begin(r), end(r)[, f])`]]
+    [[`stable_sort(r[, f])`]            [`stable_sort(begin(r), end(r)[, f])`]]
+    [[`partial_sort(r, m[, f])`]        [`partial_sort(begin(r), m, end(r)[, f])`]]
+    [[`partial_sort_copy(r1, r2[, f])`] [`partial_sort_copy(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`nth_element(r, n[, f])`]         [`nth_element(begin(r), n, end(r)[, f])`]]
+    [[`merge(r1, r2, o[, f])`]          [`merge(begin(r1), end(r1), begin(r2), end(r2), o[, f])`]]
+    [[`inplace_merge(r, m[, f])`]       [`inplace_merge(begin(r), m, end(r)[, f])`]]
+    [[`set_union(r1, r2, o[, f])`]          [`set_union(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`set_intersection(r1, r2, o[, f])`]   [`set_intersection(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`set_difference(r1, r2, o[, f])`]     [`set_difference(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`set_symmetric_difference(r1, r2, o[, f])`]   [`set_symmetric_difference(begin(r1), end(r1), begin(r2), end(r2)[, f])`]]
+    [[`push_heap(r[, f])`]              [`push_heap(begin(r), end(r)[, f])`]]
+    [[`pop_heap(r[, f])`]               [`pop_heap(begin(r), end(r)[, f])`]]
+    [[`make_heap(r[, f])`]              [`make_heap(begin(r), end(r)[, f])`]]
+    [[`sort_heap(r[, f])`]              [`sort_heap(begin(r), end(r)[, f])`]]
+    [[`next_permutation(r[, f])`]       [`next_permutation(begin(r), end(r)[, f])`]]
+    [[`prev_permutation(r[, f])`]       [`prev_permutation(begin(r), end(r)[, f])`]]
+
+    [[`inner_product(r, o, a[, f1, f2])`]   [`inner_product(begin(r), end(r), o[, f1, f2])`]]
+    [[`partial_sum(r, o[, f])`]             [`partial_sum(begin(r), end(r), o[, f])`]]
+    [[`adjacent_difference(r, o[, f])`]     [`adjacent_difference(begin(r), end(r), o[, f])`]]
+]
+
+[endsect]
+
+[section Inside Phoenix]
+
+[def __eval_policy__    [link phoenix.inside_phoenix.composites_in_detail.evalpolicy `EvalPolicy`]]
+[def __eval__           [link phoenix.inside_phoenix.actors_in_detail.eval_concept `Eval`]]
+[def __eval_tuple__     [link phoenix.inside_phoenix.composites_in_detail.evaltuple `EvalTuple`]]
+[def __environment__    [link phoenix.inside_phoenix.actors_in_detail.environment `Environment`]]
+
+This chapter explains in more detail how the library operates. The information 
+henceforth should not be necessary to those who are interested in just using the 
+library. However, a microscopic view might prove to be beneficial to moderate 
+to advanced programmers who wish to extend the library.
+
+[section Actors In Detail]
+
+[h3 Actor Concept]
+
+The main concept is the `Actor`. Actors are function objects (that can accept 0 
+to N arguments (where N is a predefined maximum).
+
+[blurb __note__ You can set `PHOENIX_LIMIT`, the predefined maximum arity an
+actor can take. By default, `PHOENIX_LIMIT` is set to 10.]
+
+[h3 actor template class]
+
+The `actor` template class models the `Actor` concept:
+    
+    template <typename Eval>
+    struct actor : Eval
+    {
+        typedef Eval eval_type;
+
+        actor();
+        actor(Eval const& base);
+
+        template <typename T0>
+        explicit actor(T0 const& _0);
+
+        template <typename T0, typename T1>
+        actor(T0 const& _0, T1 const& _1);
+        
+        // more constructors
+
+        typename apply_actor<eval_type, basic_environment<> >::type
+        operator()() const;
+
+        template <typename T0>
+        typename apply_actor<eval_type, basic_environment<T0> >::type
+        operator()(T0& _0) const;
+
+        template <typename T0, typename T1>
+        typename apply_actor<eval_type, basic_environment<T0, T1> >::type
+        operator()(T0& _0, T1& _1) const;
+
+        // function call operators
+    };
+
+[table Actor Concept Requirements
+    [   [Expression]                    [Result/Semantics]              ]
+    [   [`T::eval_type`]                [The actor's Eval type]         ]
+    [   [`T()`]                         [Default Constructor]           ]
+    [   [`T(base)`]                     [Constructor from Eval]         ]
+    [   [`T(arg0, arg1, ..., argN)`]    [Pass through constructors]     ]
+    [   [`x(arg0, arg1, ..., argN)`]    [Function call operators]       ]
+]
+
+[h3 Eval Concept]
+
+The `actor` template class has a single template parameter, `Eval`, from which 
+it derives from. While the `Actor` concept represents a function, the `Eval` 
+concept represents the function body. The requirements for `Eval` are 
+intentionally kept simple, to make it easy to write models of the concept. We 
+shall see an example in the [link phoenix.inside_phoenix.actor_example next section].
+
+[table Eval Concept Requirements
+    [   [Expression]                [Result/Semantics]                                  ]
+    [   [`return x.eval(env)`]      [Evaluates the function (see Environment below)]    ]
+    [   [`T::result<Env>::type`]    [The return type of eval (see Environment below)]   ]
+]
+
+[h3 Constructors]
+
+In addition to a default constructor and an constructor from a Eval object, 
+there are templated (pass through) constructors for 1 to N arguments (N == 
+`PHOENIX_LIMIT`). These constructors simply forward the arguments to the `base`.
+
+[blurb __note__ *Parametric Base Class Pattern*\n\n 
+    Notice that actor derives from its template argument Eval. This is the 
+    inverse of the curiously recurring template pattern (CRTP). With the CRTP, a 
+    class, T, has a Derived template parameter that is assumed to be its 
+    subclass. The "parametric base class pattern" (PBCP), on the other hand, 
+    inverses the inheritance and makes a class, T, the derived class. Both CRTP 
+    and PBCP techniques have its pros and cons, which is outside the scope of 
+    this document. CRTP should really be renamed "parametric subclass pattern 
+    (PSCP), but again, that's another story.
+]
+
+[h3 Function Call Operators]
+
+There are N function call operators for 0 to N arguments (N == `PHOENIX_LIMIT`). 
+The actor class accepts the arguments and forwards the arguments to the actor's 
+base `Eval` for evaluation. 
+
+[def [$http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm]
+
+[blurb __note__ *Forwarding Function Problem*\n\n
+    The function call operators cannot accept non-const temporaries and literal 
+    constants.  There is a known issue with current C++ called the 
+    "__forwarding__". The problem is that given an arbitrary function `F`, using 
+    current C++ language rules, one cannot create a forwarding function `FF` 
+    that transparently assumes the arguments of `F`. Disallowing non-const 
+    rvalues arguments partially solves the problem but prohibits code such as 
+    `f(1, 2, 3);`.
+]
+
+[h3 Environment]
+
+On an actor function call, before calling the actor's `Eval::eval` for 
+evaluation, the actor creates an ['*environment*]. Basically, the environment 
+packages the arguments in a tuple. The `Environment` is a concept, of which, the 
+`basic_environment` template class is a model of.
+
+[table Environment Concept Requirements
+    [   [Expression]        [Result/Semantics]                                  ]
+    [   [`x.args()`]        [The arguments in a tie (a tuple of references)]    ]
+    [   [`T::args_type`]    [The arguments' types in an MPL sequence]           ]
+    [   [`T::tie_type`]     [The tie (tuple of references) type]                ]
+]
+
+Schematically:
+
+[$images/funnel_in.png]
+
+Other parts of the library (e.g. the scope module) extends the `Environment` 
+concept to hold other information such as local variables, etc.
+
+[h3 apply_actor]
+
+`apply_actor` is a standard MPL style metafunction that simply calls the 
+Action's `result` nested metafunction:
+
+    template <typename Action, typename Env>
+    struct apply_actor
+    {
+        typedef typename Action::template result<Env>::type type;
+    };
+
+After evaluating the arguments and doing some computation, the `eval` member 
+function returns something back to the client. To do this, the forwarding 
+function (the actor's `operator()`) needs to know the return type of the eval 
+member function that it is calling. For this purpose, models of `Eval` are 
+required to provide a nested template class:
+
+    template <typename Env>
+    struct result;
+
+This nested class provides the result type information returned by the `Eval`'s 
+`eval` member function. The nested template class `result` should have a typedef 
+`type` that reflects the return type of its member function `eval`. 
+
+For reference, here's a typical `actor::operator()` that accepts two arguments:
+
+    template <typename T0, typename T1>
+    typename apply_actor<eval_type, basic_environment<T0, T1> >::type
+    operator()(T0& _0, T1& _1) const
+    {
+        return eval_type::eval(basic_environment<T0, T1>(_0, _1));
+    }
+
+[h3 actor_result]
+
+For reasons of symmetry to the family of `actor::operator()` there is a special 
+metafunction usable for actor result type calculation named `actor_result`. This 
+metafunction allows us to directly to specify the types of the parameters to be 
+passed to the `actor::operator()` function. Here's a typical `actor_result` that
+accepts two arguments:
+
+    template <typename Action, typename T0, typename T1>
+    struct actor_result
+    {
+        typedef basic_environment<T0, T1> env_type;
+        typedef typename Action::template result<env_type>::type type;
+    };
+
+[endsect]
+[section Actor Example]
+
+Let us see a very simple prototypical example of an actor. This is not a toy 
+example. This is actually part of the library. Remember the [link 
+phoenix.primitives.references `reference`]?.
+
+First, we have a model of the `Eval` concept: the `reference`:
+
+    template <typename T>
+    struct reference
+    {
+        template <typename Env>
+        struct result
+        {
+            typedef T& type;
+        };
+
+        reference(T& arg)
+            : ref(arg) {}
+
+        template <typename Env>
+        T& eval(Env const&) const
+        {
+            return ref;
+        }
+
+        T& ref;
+    };
+
+Models of `Eval` are never created directly and its instances never exist alone. 
+We have to wrap it inside the `actor` template class to be useful. The `ref` 
+template function does this for us:
+
+    template <typename T>
+    actor<reference<T> > const
+    ref(T& v)
+    {
+        return reference<T>(v);
+    }
+
+The `reference` template class conforms to the __eval__ concept. It has a nested 
+`result` metafunction that reflects the return type of its `eval` member 
+function, which peforms the actual function. `reference<T>` stores a reference to 
+a `T`. Its `eval` member function simply returns the reference. It does not make 
+use of the environment `Env`. 
+
+/Pretty simple.../
+   
+[endsect]
+[section Composites In Detail]
+
+We stated before that composites are actors that are composed of zero or more 
+actors (see [link phoenix.composite Composite]). This is not quite accurate. The 
+definition was sufficient at that point where we opted to keep things simple and 
+not bury the reader with details which she might not need anyway.
+
+Actually, a composite is a model of the __eval__ concept (more on this later). 
+At the same time, it is also composed of 0..N (where N is a predefined maximum) 
+__eval__ instances and an eval policy. The individual __eval__ instances are 
+stored in a tuple.
+
+[blurb __note__ In a sense, the original definition of "composite", more or 
+less, will do just fine because __eval__ instances never exist alone and are 
+always wrapped in an `actor` template class which inherits from it anyway. The 
+resulting actor IS-AN __eval__.]
+
+[blurb __note__ You can set `PHOENIX_COMPOSITE_LIMIT`, the predefined maximum 
+`Eval`s (actors) a composite can take. By default, `PHOENIX_COMPOSITE_LIMIT` is 
+set to `PHOENIX_LIMIT` (See [link phoenix.actors Actors]).]
+
+[h2 composite template class]
+
+    template <typename EvalPolicy, typename EvalTuple>
+    struct composite : EvalTuple
+    {
+        typedef EvalTuple base_type;
+        typedef EvalPolicy eval_policy_type;
+
+        template <typename Env>
+        struct result
+        {
+            typedef implementation-defined type;
+        };
+
+        composite();
+        composite(base_type const& actors);
+
+        template <typename U0>
+        composite(U0 const& _0);
+
+        template <typename U0, typename U1>
+        composite(U0 const& _0, U1 const& _1);
+        
+        // more constructors
+
+        template <typename Env>
+        typename result<Env>::type
+        eval(Env const& env) const;
+    };
+
+[h2 EvalTuple]
+
+`EvalTuple`, holds all the __eval__ instances. The `composite` template class 
+inherits from it. In addition to a default constructor and a constructor from an 
+`EvalTuple` object, there are templated (pass through) constructors for 1 to N 
+arguments (again, where N == `PHOENIX_COMPOSITE_LIMIT`). These constructors 
+simply forward the arguments to the `EvalTuple` base class.
+
+[h2 EvalPolicy]
+
+The composite's `eval` member function calls its `EvalPolicy`'s `eval` member 
+function (a static member function) passing in the [link 
+phoenix.inside_phoenix.actors_in_detail.environment environment] and each of 
+its actors, in parallel. The following diagram illustrates what's happening:
+
+[$images/funnel_out.png]
+
+[table EvalPolicy Requirements
+    [   [Expression]                                                [Result/Semantics]          ]
+    [   [`x.eval<RT>(env, eval0, eval1, ..., evalN)`]               [Evaluate the composite]    ]
+    [   [`T::result<Env, Eval0, Eval1, Eval2, ..., EvalN>::type`]   [The return type of eval]   ]
+]
+
+The `EvalPolicy` is expected to have a nested template class `result` which has a 
+typedef `type` that reflects the return type of its member function `eval`. 
+Here's a typical example of the composite's eval member function for a 2-actor 
+composite:
+
+    template <typename Env>
+    typename result<Env>::type
+    eval(Env const& env) const
+    {
+        typedef typename result<Env>::type return_type;
+        return EvalPolicy::template 
+            eval<return_type>(
+                env
+              , get<0>(*this)   // gets the 0th element from EvalTuple
+              , get<1>(*this)); // gets the 1st element from EvalTuple    
+    }
+
+[endsect]
+[section Composing]
+
+Composites are never instantiated directly. Front end expression templates are 
+used to generate the composites. Using expression templates, we implement a DSEL 
+(Domain Specific Embedded Language) that mimicks native C++. You've seen this 
+DSEL in action in the preceding sections. It is most evident in the 
+[link phoenix.composite.statement Statement] section.
+
+There are some facilities in the library to make composition of composites 
+easier. We have a set of overloaded `compose` functions and an `as_composite` 
+metafunction. Together, these helpers make composing a breeze. We'll provide an 
+[link phoenix.inside_phoenix.composing.composite_example example of a 
+composite] later to see why.
+
+[section compose]
+
+    compose<EvalPolicy>(arg0, arg1, arg2, ..., argN);
+
+Given an __eval_policy__ and some arguments `arg0`...argN, returns a proper 
+`composite`. The arguments may or may not be phoenix actors (primitives of 
+composites). If not, the arguments are converted to actors appropriately. For 
+example:
+
+    compose<X>(3)
+
+converts the argument `3` to an `actor<value<int> >(3)`.
+    
+[endsect]
+
+[section as_composite]
+
+    as_composite<EvalPolicy, Arg0, Arg1, Arg2, ..., ArgN>::type
+
+This is the metafunction counterpart of `compose`. Given an __eval_policy__ and 
+some argument types `Arg0`...ArgN, returns a proper `composite` type. For 
+example:
+
+    as_composite<X, int>::type
+
+is the composite type of the `compose<X>(3)` expression above.
+
+[endsect]
+
+[section Composite Example]
+
+Now, let's examine an example. Again, this is not a toy example. This is actually 
+part of the library. Remember the [link phoenix.composite.statement.while__statement 
+`while_`] lazy statement? Putting together everything we've learned so far, we 
+will present it here in its entirety (verbatim):
+
+    struct while_eval
+    {
+        template <typename Env, typename Cond, typename Do>
+        struct result
+        {
+            typedef void type;
+        };
+
+        template <typename RT, typename Env, typename Cond, typename Do>
+        static void
+        eval(Env const& env, Cond& cond, Do& do_)
+        {
+            while (cond.eval(env))
+                do_.eval(env);
+        }
+    };
+
+    template <typename Cond>
+    struct while_gen
+    {
+        while_gen(Cond const& cond)
+            : cond(cond) {}
+
+        template <typename Do>
+        actor<typename as_composite<while_eval, Cond, Do>::type>
+        operator[](Do const& do_) const
+        {
+            return compose<while_eval>(cond, do_);
+        }
+
+        Cond cond;
+    };
+
+    template <typename Cond>
+    while_gen<Cond>
+    while_(Cond const& cond)
+    {
+        return while_gen<Cond>(cond);
+    }
+    
+`while_eval` is an example of an __eval_policy__. `while_gen` and `while_` are 
+the expression template front ends. Let's break this apart to understand what's 
+happening. Let's start at the bottom. It's easier that way.
+
+When you write:
+
+    while_(cond)
+
+we generate an instance of `while_gen<Cond>`, where `Cond` is the type of 
+`cond`. `cond` can be an arbitrarily complex actor expression. The `while_gen` 
+template class has an `operator[]` accepting another expression. If we write:
+
+    while_(cond)
+    [
+        do_
+    ]
+
+it will generate a proper composite with the type:
+
+    as_composite<while_eval, Cond, Do>::type
+
+where `Cond` is the type of `cond` and `Do` is the type of `do_`. Notice how we 
+are using phoenix's [link phoenix.inside_phoenix.composing composition] (`compose` 
+and `as_composite`) mechanisms here
+
+    template <typename Do>
+    actor<typename as_composite<while_eval, Cond, Do>::type>
+    operator[](Do const& do_) const
+    {
+        return compose<while_eval>(cond, do_);
+    }
+
+Finally, the `while_eval` does its thing:
+
+    while (cond.eval(env))
+        do_.eval(env);
+
+`cond` and `do_`, at this point, are instances of __eval__. `cond` and `do_` are 
+the __eval__ elements held by the composite's __eval_tuple__. `env` is the 
+__environment__.
+
+[endsect]
+
+[endsect]
+
+[section Extending]
+
+We've shown how it is very easy to extend phoenix by writing new primitives and 
+composites. The modular design of Phoenix makes it extremely extensible. We have 
+seen that layer upon layer, the whole library is built on a solid foundation. 
+There are only a few simple well designed concepts that are laid out like 
+bricks. Overall, the library is designed to be extended. Everything above the 
+core layer can in fact be considered just as extensions to the library. This 
+modular design was inherited from the __spirit__ inline parser library.
+
+Extension is non-intrusive. And, whenever a component or module is extended, the 
+new extension automatically becomes a first class citizen and is automatically 
+recognized by all modules and components in the library.
+
+[endsect]
+
+[endsect]
+
+[section Wrap Up]
+
+Sooner or later more FP techniques become standard practice as people find the 
+true value of this programming discipline outside the academe and into the 
+mainstream. In as much as structured programming of the 70s and object oriented 
+programming in the 80s and generic programming in the 90s shaped our thoughts 
+towards a more robust sense of software engineering, FP will certainly be a 
+paradigm that will catapult us towards more powerful software design and 
+engineering onward into the new millenium.
+
+Let me quote Doug Gregor of Boost.org. About functional style programming 
+libraries:
+
+[:['They're gaining acceptance, but are somewhat stunted by the ubiquitousness 
+of broken compilers. The C++ community is moving deeper into the so-called "STL-
+style" programming paradigm, which brings many aspects of functional programming 
+into the fold. Look at, for instance, the Spirit parser to see how such function 
+objects can be used to build Yacc-like grammars with semantic actions that can 
+build abstract syntax trees on the fly. This type of functional composition is 
+gaining momentum.]]
+
+Indeed. Phoenix is another attempt to introduce more FP techniques into the 
+mainstream. Not only is it a tool that will make life easier for the programmer. 
+In its own right, the actual design of the library itself is a model of true C++ 
+FP in action. The library is designed and structured in a strict but clear and 
+well mannered FP sense. By all means, use the library as a tool. But for those 
+who want to learn more about FP in C++, don't stop there, I invite you to take a 
+closer look at the design of the library itself.
+
+So there you have it. Have fun! See you in the FP world.
+
+[endsect]
+
+[section Acknowledgement]
+
+# Hartmut Kaiser implemented the original lazy casts and constructors based on 
+  his original work on Spirit SE "semantic expressions" (the precursor to 
+  Phoenix).
+# Angus Leeming implemented the container functions on Phoenix-1 which I then
+  ported to Phoenix-2.
+# Daniel Wallin helped with the scope module, local variables, let and lambda
+  and the algorithms. I frequently discuss design issues with Daniel on Yahoo Messenger.
+# Jaakko Jarvi. DA Lambda MAN!
+# Dave Abrahams, for his constant presence, wherever, whenever.
+# Aleksey Gurtovoy, DA MPL MAN!
+# Doug Gregor, always a source of inpiration.
+# Dan Marsden, did almost all the work in bringing Phoenix-2 out the door.
+# Eric Niebler did a 2.0 pre-release review and wrote some range related code
+  that Phoenix stole and used in the algorithms.
+# Thorsten Ottosen; Eric's range_ex code began life as "container_algo" in the 
+  old boost sandbox, by Thorsten in 2002-2003.
+# Jeremy Siek, even prior to Thorsten, in 2001, started the "container_algo".
+# Vladimir Prus wrote the mutating algorithms code from the Boost Wiki.
+# Daryle Walker did a 2.0 pre-release review.
+
+[endsect]
+
+[section References]
+
+# Why Functional Programming Matters, John Hughes, 1989.
+  Available online at [@http://www.math.chalmers.se/~rjmh/Papers/whyfp.html].
+# Boost.Lambda library, Jaakko Jarvi, 1999-2004 Jaakko Jarvi, Gary Powell.
+  Available online at [@http://www.boost.org/libs/lambda/].
+# Functional Programming in C++ using the FC++ Library: a short article 
+  introducing FC++, Brian McNamara and Yannis Smaragdakis, August 2003. Available 
+  online at [@http://www.cc.gatech.edu/~yannis/fc++/].
+# Side-effects and partial function application in C++, Jaakko Jarvi and Gary 
+  Powell, 2001. Available online at 
+  [@http://osl.iu.edu/~jajarvi/publications/papers/mpool01.pdf].
+# Spirit Version 1.8.1, Joel de Guzman, Nov 2004. Available online at 
+  [@http://www.boost.org/libs/spirit/].
+# The Boost MPL Library, Aleksey Gurtovoy and David Abrahams, 2002-2004. 
+  Available online at [@http://www.boost.org/libs/mpl/].
+# Generic Programming Redesign of Patterns, Proceedings of the 5th European 
+  Conference on Pattern Languages of Programs, (EuroPLoP'2000) Irsee, Germany, 
+  July 2000. Available online at 
+  [@http://www.coldewey.com/europlop2000/papers/geraud%2Bduret.zip].
+# A Gentle Introduction to Haskell, Paul Hudak, John Peterson and Joseph Fasel, 
+  1999. Available online at [@http://www.haskell.org/tutorial/].
+# Large scale software design, John Lackos, ISBN 0201633620, Addison-Wesley, July 
+  1996.
+# Design Patterns, Elements of Reusable Object-Oriented Software, Erich Gamma, 
+  Richard Helm, Ralph Jhonson, and John Vlissides, Addison-Wesley, 1995.
+# The Forwarding Problem: Arguments Peter Dimov, Howard E. Hinnant, Dave 
+  Abrahams, September 09, 2002. Available online: __forwarding__.
+
+[endsect]
+
Added: trunk/libs/spirit/phoenix/example/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/Jamfile.v2	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,24 @@
+#==============================================================================
+#    Copyright (c) 2003, 2005 Joel de Guzman
+#
+#   Use, modification and distribution is subject to the Boost Software
+#   License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+#   http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+
+# bring in rules for testing
+import testing ;
+
+test-suite users_manual :
+    [ run users_manual/all_odds.cpp ] 
+    [ run users_manual/arguments.cpp ] 
+    [ run users_manual/callback.cpp ] 
+    [ run users_manual/factorial.cpp ] 
+    [ run users_manual/find_if.cpp ] 
+    [ run users_manual/function.cpp ] 
+    [ run users_manual/if.cpp ] 
+    [ run users_manual/lambda.cpp ] 
+    [ run users_manual/values.cpp ] 
+    [ run users_manual/references.cpp ] 
+    ;
+
Added: trunk/libs/spirit/phoenix/example/users_manual/algorithm.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/algorithm.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,21 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_algorithm.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+
+int
+main()
+{
+    int array[] = {1, 2, 3};
+    int output[3];
+    copy(arg1, arg2)(array, output);
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/all_odds.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/all_odds.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,35 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int init[] = { 2, 10, 4, 5, 1, 6, 8, 3, 9, 7 };
+    vector<int> c(init, init + 10);
+    typedef vector<int>::iterator iterator;
+
+    //  Print all odd contents of an stl container c
+    for_each(c.begin(), c.end(),
+        if_(arg1 % 2 == 1)
+        [
+            cout << arg1 << ' '
+        ]
+    );
+
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/arguments.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/arguments.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,22 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int i = 3;
+    char const* s = "Hello World";
+    cout << arg1(i) << endl;        // prints 3
+    cout << arg2(i, s) << endl;     // prints "Hello World"
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/callback.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/callback.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,26 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+template <typename F>
+void print(F f)
+{
+    cout << f() << endl;
+}
+
+int
+main()
+{
+    print(val(3));
+    print(val("Hello World"));
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/factorial.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/factorial.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,40 @@
+/*=============================================================================
+    Copyright (c) 2001-2003 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 <vector>
+#include <algorithm>
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+struct factorial_impl
+{
+    template <typename Arg>
+    struct result
+    {
+        typedef Arg type;
+    };
+
+    template <typename Arg>
+    Arg operator()(Arg n) const
+    {
+        return (n <= 0) ? 1 : n * this->operator()(n-1);
+    }
+};
+
+function<factorial_impl> factorial;
+
+int
+main()
+{
+    int i = 4;
+    cout << factorial(arg1)(i) << endl;
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/find_if.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/find_if.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,30 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <vector>
+#include <algorithm>
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int init[] = { 2, 10, 4, 5, 1, 6, 8, 3, 9, 7 };
+    vector<int> c(init, init + 10);
+    typedef vector<int>::iterator iterator;
+
+    //  Find the first odd number in container c
+    iterator it = find_if(c.begin(), c.end(), arg1 % 2 == 1);
+
+    if (it != c.end())
+        cout << *it;    //  if found, print the result
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/function.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/function.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,47 @@
+/*=============================================================================
+    Copyright (c) 2001-2003 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 <vector>
+#include <algorithm>
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+struct is_odd_ 
+{
+    template <typename Arg>
+    struct result 
+    { 
+        typedef bool type; 
+    };
+
+    template <typename Arg>
+    bool operator()(Arg arg1) const
+    { 
+        return arg1 % 2 == 1; 
+    }
+};
+
+function<is_odd_> is_odd;
+
+int
+main()
+{
+    int init[] = { 2, 10, 4, 5, 1, 6, 8, 3, 9, 7 };
+    vector<int> c(init, init + 10);
+    typedef vector<int>::iterator iterator;
+
+    //  Find the first odd number in container c
+    iterator it = find_if(c.begin(), c.end(), is_odd(arg1));
+
+    if (it != c.end())
+        cout << *it;    //  if found, print the result
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/if.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/if.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,35 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+    vector<int> v(init, init+10);
+
+    cout << dec;
+    int x = 0;
+
+    for_each(v.begin(), v.end(),
+        if_(arg1 > 5)
+        [
+            cout << arg1 << ", "
+        ]
+    );
+
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/lambda.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/lambda.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,79 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <algorithm>
+#include <vector>
+
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_scope.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace boost::phoenix::local_names;
+using namespace std;
+
+namespace lazy_stuff
+{
+    struct for_each_impl
+    {
+        template <typename C, typename F>
+        struct result
+        {
+            typedef void type;
+        };
+
+        template <typename C, typename F>
+        void operator()(C& c, F f) const
+        {
+            std::for_each(c.begin(), c.end(), f);
+        }
+    };
+
+    function<for_each_impl> const for_each = for_each_impl();
+
+    struct push_back_impl
+    {
+        template <typename C, typename T>
+        struct result
+        {
+            typedef void type;
+        };
+
+        template <typename C, typename T>
+        void operator()(C& c, T& x) const
+        {
+            c.push_back(x);
+        }
+    };
+
+    function<push_back_impl> const push_back = push_back_impl();
+}
+
+int
+main()
+{
+    {
+        using lazy_stuff::for_each;
+        using lazy_stuff::push_back;
+
+        int x = 10;
+        std::vector<std::vector<int> > v(10);
+
+        for_each(arg1, 
+            lambda(_a = arg2)
+            [
+                push_back(arg1, _a)
+            ]
+        )
+        (v, x);
+    }
+
+    return 0;
+}
+
Added: trunk/libs/spirit/phoenix/example/users_manual/references.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/references.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,22 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int i = 3;
+    char const* s = "Hello World";
+    cout << ref(i)() << endl;
+    cout << ref(s)() << endl;
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/example/users_manual/values.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/example/users_manual/values.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,20 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    cout << val(3)() << endl;
+    cout << val("Hello World")() << endl;
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/index.html
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/index.html	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <meta http-equiv="refresh" content="0; URL=doc/html/index.html">
+  </head>
+  <body>
+    Automatic redirection failed, click this 
+    link
+  </body>
+</html>
Added: trunk/libs/spirit/phoenix/test/Jamfile.v2
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/Jamfile.v2	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,90 @@
+#==============================================================================
+#    Copyright (c) 2003-2006 Joel de Guzman
+#
+#   Use, modification and distribution is subject to the Boost Software
+#   License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+#   http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+
+# bring in rules for testing
+import testing ;
+
+local multi-threading = <library>/boost/thread//boost_thread 
+                        <threading>multi <define>BOOST_ALL_NO_LIB=1 ;
+
+test-suite phoenix_detail :
+    [ run detail/type_deduction_tests.cpp ] 
+    ;
+
+test-suite phoenix_core :
+    [ run core/primitives_tests.cpp ] 
+    [ run core/compose_tests.cpp ] 
+    ;
+
+test-suite phoenix_operator :
+    [ run operator/arithmetic_tests.cpp ] 
+    [ run operator/bitwise_tests.cpp ] 
+    [ run operator/comparison_tests.cpp ] 
+    [ run operator/if_else_tests.cpp ] 
+    [ run operator/io_tests.cpp ] 
+    [ run operator/logical_tests.cpp ] 
+    [ run operator/misc_binary_tests.cpp ] 
+    [ run operator/self_tests.cpp ] 
+    [ run operator/unary_tests.cpp ] 
+    [ run operator/member.cpp ]
+    ;
+
+test-suite phoenix_object :
+    [ run object/cast_tests.cpp ] 
+    [ run object/new_delete_tests.cpp ] 
+    ;
+
+test-suite phoenix_function :
+    [ run function/function_tests.cpp ] 
+    ;
+
+test-suite phoenix_bind :
+    [ run bind/bind_function_tests.cpp ] 
+    [ run bind/bind_function_object_tests.cpp ] 
+    [ run bind/bind_member_function_tests.cpp ]
+    [ run bind/bind_member_variable_tests.cpp ]
+    ;
+    
+test-suite phoenix_statement :
+    [ run statement/if_tests.cpp ] 
+    [ run statement/loops_tests.cpp ] 
+    [ run statement/switch_tests.cpp ] 
+    [ run statement/exceptions.cpp ]
+    ;
+        
+test-suite phoenix_container :
+    [ run container/container_tests1a.cpp ] 
+    [ run container/container_tests1b.cpp ] 
+    [ run container/container_tests2a.cpp ] 
+    [ run container/container_tests2b.cpp ] 
+    [ run container/container_tests3a.cpp ] 
+    [ run container/container_tests3b.cpp ] 
+    [ run container/container_tests4a.cpp ] 
+    [ run container/container_tests4b.cpp ] 
+    [ run container/container_tests5a.cpp ] 
+    [ run container/container_tests5b.cpp ] 
+    [ run container/container_tests6a.cpp ] 
+    [ run container/container_tests6b.cpp ] 
+    ;
+
+test-suite phoenix_scope :
+    [ run scope/lambda_tests.cpp ] 
+    [ run scope/let_tests.cpp ] 
+    [ run scope/dynamic_tests.cpp ] 
+    [ run scope/bug_000008.cpp : : : $(multi-threading) ] 
+    ;
+
+test-suite phoenix_algorithm :
+    [ run algorithm/iteration.cpp ]
+    [ run algorithm/transformation1.cpp ]
+    [ run algorithm/transformation2.cpp ]
+    [ run algorithm/transformation3.cpp ]
+    [ run algorithm/transformation4.cpp ]
+    [ run algorithm/querying.cpp ]
+    [ run algorithm/querying2.cpp ]
+    ;
Added: trunk/libs/spirit/phoenix/test/algorithm/iteration.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/algorithm/iteration.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,57 @@
+/*=============================================================================
+    Copyright (c) 2005-2007 Dan Marsden
+    Copyright (c) 2005-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)
+==============================================================================*/
+
+#include <boost/spirit/include/phoenix_stl.hpp/iteration.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <functional>
+
+namespace
+{
+    struct for_each_tester
+    {
+        int value_;
+        for_each_tester() : value_(0) { }
+        void operator()(
+            int& i)
+        {
+            value_ += i++;
+            return;
+        }
+    };
+
+    void for_each_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        BOOST_TEST(for_each(arg1, for_each_tester())(array).value_ == 6);
+        BOOST_TEST(array[0] == 2);
+        BOOST_TEST(array[1] == 3);
+        BOOST_TEST(array[2] == 4);
+        return;
+    }
+
+    void accumulate_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        BOOST_TEST(accumulate(arg1, 0)(array) == 6);
+        BOOST_TEST(boost::phoenix::accumulate(arg1, 0, std::minus<int>())(array) == -6);
+        return;
+    }
+}
+
+int main()
+{
+    for_each_test();
+    accumulate_test();
+    boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/algorithm/querying.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/algorithm/querying.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,270 @@
+/*=============================================================================
+    Copyright (c) 2005 Dan Marsden
+    Copyright (c) 2005-2007 Joel de Guzman
+    Copyright (c) 2007 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 <boost/spirit/include/phoenix_stl.hpp/querying.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <set>
+#include <functional>
+
+namespace
+{
+    struct even
+    {
+        bool operator()(const int i) const
+        {
+            return i % 2 == 0;
+        }
+    };
+
+    struct mod_2_comparison
+    {
+        bool operator()(
+            const int lhs,
+            const int rhs)
+        {
+            return lhs % 2 == rhs % 2;
+        };
+    };
+
+    void find_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        BOOST_TEST(find(arg1,2)(array) == array + 1);
+
+        std::set<int> s(array, array + 3);
+        BOOST_TEST(find(arg1, 2)(s) == s.find(2));
+
+        return;
+    }
+
+
+    void find_if_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        BOOST_TEST(find_if(arg1, even())(array) == array + 1);
+        return;
+    }
+
+    void find_end_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3,1,2,3,1};
+        int pattern[] = {1,2,3};
+        BOOST_TEST(find_end(arg1, arg2)(array, pattern) == array + 3);
+        int pattern2[] = {5,6,5};
+        BOOST_TEST(find_end(arg1, arg2, mod_2_comparison())(array, pattern2) == array + 3);
+        return;
+    }
+
+    void find_first_of_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int search_for[] = {2,3,4};
+        BOOST_TEST(find_first_of(arg1, arg2)(array, search_for) == array + 1);
+
+        int search_for2[] = {0};
+        BOOST_TEST(find_first_of(arg1, arg2, mod_2_comparison())(array, search_for2) == array + 1);
+        return;
+    }
+
+    void adjacent_find_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {0,1,3,4,4};
+        BOOST_TEST(adjacent_find(arg1)(array) == array + 3);
+        BOOST_TEST(adjacent_find(arg1, mod_2_comparison())(array) == array + 1);
+        return;
+    }
+
+    void count_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,1,0,1,1};
+        BOOST_TEST(count(arg1, 1)(array) == 4);
+        return;
+    }
+
+    void count_if_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3,4,5};
+        BOOST_TEST(count_if(arg1, even())(array) == 2);
+        return;
+    }
+
+    void distance_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,1,0,1,1};
+        BOOST_TEST(distance(arg1)(array) == 5);
+        return;
+    }
+
+    void mismatch_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3,4,5};
+        int search[] = {1,2,4};
+
+        BOOST_TEST(
+            mismatch(arg1, arg2)(array, search) == 
+            std::make_pair(array + 2, search + 2));
+        int search2[] = {1,2,1,1};
+        BOOST_TEST(
+            mismatch(arg1, arg2, mod_2_comparison())(array, search2) 
+            == std::make_pair(array + 3, search2 + 3));
+
+        return;
+    }
+
+    void equal_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[] = {1,2,3};
+        int array3[] = {1,2,4};
+        BOOST_TEST(
+            equal(arg1, arg2)(array, array2));
+        BOOST_TEST(
+            !equal(arg1, arg2)(array, array3));
+
+        BOOST_TEST(
+            equal(arg1, arg2, mod_2_comparison())(array, array2));
+        BOOST_TEST(
+            !equal(arg1, arg2, mod_2_comparison())(array, array3));
+        return;
+    }
+
+    void search_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3,1,2,3};
+        int pattern[] = {2,3};
+        BOOST_TEST(
+            search(arg1, arg2)(array, pattern) == array + 1);
+        int pattern2[] = {1,1};
+        BOOST_TEST(
+            search(arg1, arg2, mod_2_comparison())(array, pattern2) == array + 2);
+        return;
+    }
+
+    void lower_bound_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        const std::set<int> test_set(array, array + 3);
+        BOOST_TEST(lower_bound(arg1, 2)(array) == array + 1);
+        BOOST_TEST(lower_bound(arg1, 2)(test_set) == test_set.lower_bound(2));
+
+        int array2[] = {3,2,1};
+        const std::set<int, std::greater<int> > test_set2(array2, array2 + 3);
+        BOOST_TEST(boost::phoenix::lower_bound(arg1, 2, std::greater<int>())(array2) ==
+                   array2 + 1);
+        BOOST_TEST(boost::phoenix::lower_bound(arg1, 2, std::greater<int>())(test_set2) ==
+                   test_set2.lower_bound(2));
+        return;
+    }
+
+    void upper_bound_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        const std::set<int> test_set(array, array + 3);
+        BOOST_TEST(upper_bound(arg1, 2)(array) == array + 2);
+        BOOST_TEST(upper_bound(arg1, 2)(test_set) == test_set.upper_bound(2));
+
+        int array2[] = {3,2,1};
+        const std::set<int, std::greater<int> > test_set2(array2, array2 + 3);
+        BOOST_TEST(boost::phoenix::upper_bound(arg1, 2, std::greater<int>())(array2) ==
+                   array2 + 2);
+        BOOST_TEST(boost::phoenix::upper_bound(arg1, 2, std::greater<int>())(test_set2) ==
+                   test_set2.upper_bound(2));
+        return;
+    }
+
+    void equal_range_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,2,3};
+        const std::set<int> test_set(array, array + 4);
+        BOOST_TEST(equal_range(arg1, 2)(array).first == 
+                   array + 1);
+        BOOST_TEST(equal_range(arg1, 2)(array).second == 
+                   array + 3);
+
+        BOOST_TEST(equal_range(arg1, 2)(test_set).first == 
+                   test_set.equal_range(2).first);
+        BOOST_TEST(equal_range(arg1, 2)(test_set).second == 
+                   test_set.equal_range(2).second);
+
+        int array2[] = {3,2,2,1};
+        const std::set<int, std::greater<int> > test_set2(array2, array2 + 4);
+        BOOST_TEST(boost::phoenix::equal_range(arg1, 2, std::greater<int>())(array2).first == 
+                   array2 + 1);
+        BOOST_TEST(boost::phoenix::equal_range(arg1, 2, std::greater<int>())(array2).second == 
+                   array2 + 3);
+
+        BOOST_TEST(boost::phoenix::equal_range(arg1, 2, std::greater<int>())(test_set2).first == 
+                   test_set2.equal_range(2).first);
+        BOOST_TEST(boost::phoenix::equal_range(arg1, 2, std::greater<int>())(test_set2).second == 
+                   test_set2.equal_range(2).second);
+
+        return;
+    }
+
+    void binary_search_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        BOOST_TEST(binary_search(arg1, 2)(array));
+        BOOST_TEST(!binary_search(arg1, 4)(array));
+        return;
+    }
+
+}
+
+int main()
+{
+    find_test();
+    find_if_test();
+    find_end_test();
+    find_first_of_test();
+    adjacent_find_test();
+    count_test();
+    count_if_test();
+    distance_test();
+    mismatch_test();
+    equal_test();
+    search_test();
+    lower_bound_test();
+    upper_bound_test();
+    equal_range_test();
+    binary_search_test();
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/algorithm/querying2.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/algorithm/querying2.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,83 @@
+/*=============================================================================
+    Copyright (c) 2005-2007 Dan Marsden
+    Copyright (c) 2005-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)
+==============================================================================*/
+
+#include <boost/spirit/include/phoenix_stl.hpp/querying.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/range.hpp>
+
+#include <functional>
+
+namespace
+{
+    void includes_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[] = {1,2};
+        BOOST_TEST(includes(arg1, arg2)(array, array2));
+        boost::iterator_range<int*> rng(array + 1, array + 3);
+        BOOST_TEST(!includes(arg1, arg2)(rng, array2));
+
+        int array3[] = {3,2,1};
+        int array4[] = {2,1};
+        BOOST_TEST(boost::phoenix::includes(arg1, arg2, std::greater<int>())(array3, array4));
+        boost::iterator_range<int*> rng2(array3, array3 + 2);
+        BOOST_TEST(!boost::phoenix::includes(arg1, arg2, std::greater<int>())(rng2, array4));
+        return;
+    }
+
+    void min_element_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,3,2};
+        BOOST_TEST(min_element(arg1)(array) == array);
+        BOOST_TEST(boost::phoenix::min_element(arg1, std::greater<int>())(array) == array + 1);
+        return;
+    }
+
+    void max_element_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,3,2};
+        BOOST_TEST(max_element(arg1)(array) == array + 1);
+        BOOST_TEST(boost::phoenix::max_element(arg1, std::greater<int>())(array) == array);
+        return;
+    }
+
+    void lexicographical_compare_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[] = {1,2,4};
+
+        BOOST_TEST(lexicographical_compare(arg1, arg2)(array, array2));
+        BOOST_TEST(!lexicographical_compare(arg1, arg2)(array2, array));
+        BOOST_TEST(!lexicographical_compare(arg1, arg2)(array, array));
+
+        BOOST_TEST(!boost::phoenix::lexicographical_compare(arg1, arg2, std::greater<int>())(array, array2));
+        BOOST_TEST(boost::phoenix::lexicographical_compare(arg1, arg2, std::greater<int>())(array2, array));
+        BOOST_TEST(!boost::phoenix::lexicographical_compare(arg1, arg2, std::greater<int>())(array, array));
+
+        return;
+    }
+}
+
+int main()
+{
+    includes_test();
+    min_element_test();
+    max_element_test();
+    lexicographical_compare_test();
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/algorithm/transformation1.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/algorithm/transformation1.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,390 @@
+/*=============================================================================
+    Copyright (c) 2005-2007 Dan Marsden
+    Copyright (c) 2005-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)
+==============================================================================*/
+
+#include <boost/spirit/include/phoenix_stl.hpp/transformation.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <functional>
+#include <list>
+
+namespace
+{
+    struct even
+    {
+        bool operator()(const int i) const
+        {
+            return i % 2 == 0;
+        }
+    };
+
+    struct mod_2_comparison
+    {
+        bool operator()(
+            const int lhs,
+            const int rhs)
+        {
+            return lhs % 2 == rhs % 2;
+        };
+    };
+
+    void swap_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int a = 123;
+        int b = 456;
+        swap(ref(a), ref(b))();
+        BOOST_TEST(a == 456 && b == 123);
+        swap(ref(a), _1)(b);
+        BOOST_TEST(a == 123 && b == 456);
+        swap(_1, _2)(a, b);
+        BOOST_TEST(a == 456 && b == 123);
+        return;
+    }
+
+    void copy_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int output[4];
+        BOOST_TEST(
+            copy(arg1, arg2)(array, output) == output + 3);
+        BOOST_TEST(output[0] == 1);
+        BOOST_TEST(output[1] == 2);
+        BOOST_TEST(output[2] == 3);
+        return;
+    }
+
+    void copy_backward_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int output[4];
+        int* output_end = output + 3;
+        BOOST_TEST(
+            copy_backward(arg1, arg2)(array, output_end) == output);
+        BOOST_TEST(output[0] == 1);
+        BOOST_TEST(output[1] == 2);
+        BOOST_TEST(output[2] == 3);
+        return;
+    }
+
+    struct increment
+    {
+        int operator()(
+            int i) const
+        {
+            return i+1;
+        }
+    };
+
+    void transform_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        BOOST_TEST(
+            transform(arg1, arg2, increment())(array, array) == 
+            array + 3);
+        BOOST_TEST(array[0] == 2);
+        BOOST_TEST(array[1] == 3);
+        BOOST_TEST(array[2] == 4);
+
+        int array2[] = {1,2,3};
+        BOOST_TEST(
+            boost::phoenix::transform(arg1, arg2, arg3, std::plus<int>())(array, array2, array) == 
+            array +3);
+        BOOST_TEST(array[0] == 2 + 1);
+        BOOST_TEST(array[1] == 3 + 2);
+        BOOST_TEST(array[2] == 4 + 3);
+        return;
+    }
+
+    void replace_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        replace(arg1,2,4)(array);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 4);
+        BOOST_TEST(array[2] == 3);
+        return;
+    }
+
+    void replace_if_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        replace_if(arg1, even(), 4)(array);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 4);
+        BOOST_TEST(array[2] == 3);
+        return;
+    }
+
+    void replace_copy_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int input[] = {1,2,3};
+        int output[3];
+        replace_copy(arg1, arg2, 2, 4)(input, output);
+        BOOST_TEST(output[0] == 1);
+        BOOST_TEST(output[1] == 4);
+        BOOST_TEST(output[2] == 3);
+        return;
+    }
+
+    void replace_copy_if_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int input[] = {1,2,3};
+        int output[3];
+        replace_copy_if(arg1, arg2, even(), 4)(input, output);
+        BOOST_TEST(output[0] == 1);
+        BOOST_TEST(output[1] == 4);
+        BOOST_TEST(output[2] == 3);
+        return;
+    }
+
+    void fill_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {0,0,0};
+        fill(arg1, 1)(array);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 1);
+        BOOST_TEST(array[2] == 1);
+        return;
+    }
+
+    void fill_n_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {0,0,0};
+        fill_n(arg1, 2, 1)(array);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 1);
+        BOOST_TEST(array[2] == 0);
+        return;
+    }
+
+    class int_seq
+    {
+    public:
+        int_seq() : val_(0) { }
+
+        int operator()()
+        {
+            return val_++;
+        }
+    private:
+        int val_;
+    };
+
+    void generate_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[3];
+        generate(arg1, int_seq())(array);
+        BOOST_TEST(array[0] == 0);
+        BOOST_TEST(array[1] == 1);
+        BOOST_TEST(array[2] == 2);
+        return;
+    }
+
+    void generate_n_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {0,0,1};
+        generate_n(arg1, 2, int_seq())(array);
+        BOOST_TEST(array[0] == 0);
+        BOOST_TEST(array[1] == 1);
+        BOOST_TEST(array[2] == 1);
+        return;
+    }
+
+
+    void remove_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        std::list<int> test_list(array, array + 3);
+        BOOST_TEST(boost::phoenix::remove(arg1, 2)(array) == array + 2);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 3);
+        BOOST_TEST(boost::phoenix::remove(arg1, 2)(test_list) == test_list.end());
+        std::list<int>::const_iterator it(test_list.begin());
+        BOOST_TEST(*it++ == 1);
+        BOOST_TEST(*it++ == 3);
+        return;
+    }
+
+    void remove_if_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        std::list<int> test_list(array, array + 3);
+        BOOST_TEST(boost::phoenix::remove_if(arg1, even())(array) == array + 2);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 3);
+        BOOST_TEST(boost::phoenix::remove_if(arg1, even())(test_list) == test_list.end());
+        std::list<int>::const_iterator it(test_list.begin());
+        BOOST_TEST(*it++ == 1);
+        BOOST_TEST(*it++ == 3);
+        return;
+    }
+
+    void remove_copy_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[2];
+        BOOST_TEST(boost::phoenix::remove_copy(arg1, arg2, 2)(array, array2) == array2 + 2);
+        BOOST_TEST(array2[0] == 1);
+        BOOST_TEST(array2[1] == 3);
+        return;
+    }
+
+    void remove_copy_if_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[2];
+        BOOST_TEST(boost::phoenix::remove_copy_if(arg1, arg2, even())(array, array2) == array2 + 2);
+        BOOST_TEST(array2[0] == 1);
+        BOOST_TEST(array2[1] == 3);
+        return;
+    }
+
+    void unique_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,2,3};
+        std::list<int> test_list(array, array + 4);
+        BOOST_TEST(unique(arg1)(array) == array + 3);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 2);
+        BOOST_TEST(array[2] == 3);
+
+        BOOST_TEST(unique(arg1)(test_list) == test_list.end());
+        std::list<int>::const_iterator it(test_list.begin());
+        BOOST_TEST(*it++ == 1);
+        BOOST_TEST(*it++ == 2);
+        BOOST_TEST(*it++ == 3);
+
+        int array2[] = {1,3,2};
+        std::list<int> test_list2(array2, array2 + 3);
+        BOOST_TEST(unique(arg1, mod_2_comparison())(array2) == array2 + 2);
+        BOOST_TEST(array2[0] == 1);
+        BOOST_TEST(array2[1] == 2);
+        
+        BOOST_TEST(unique(arg1, mod_2_comparison())(test_list2) == test_list2.end());
+        std::list<int>::const_iterator jt(test_list2.begin());
+        BOOST_TEST(*jt++ == 1);
+        BOOST_TEST(*jt++ == 2);
+        
+        return;
+    }
+
+    void unique_copy_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,2,3};
+        int out[3];
+        BOOST_TEST(unique_copy(arg1, arg2)(array, out) == out + 3);
+        BOOST_TEST(out[0] == 1);
+        BOOST_TEST(out[1] == 2);
+        BOOST_TEST(out[2] == 3);
+
+        int array2[] = {1,3,2};
+        int out2[2];
+        BOOST_TEST(unique_copy(arg1, arg2, mod_2_comparison())(array2, out2) == out2 + 2);
+        BOOST_TEST(out2[0] == 1);
+        BOOST_TEST(out2[1] == 2);
+        
+        return;
+    }
+
+    void reverse_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        std::list<int> test_list(array, array + 3);
+        reverse(arg1)(array);
+        BOOST_TEST(array[0] == 3);
+        BOOST_TEST(array[1] == 2);
+        BOOST_TEST(array[2] == 1);
+
+        reverse(arg1)(test_list);
+        std::list<int>::iterator it(test_list.begin());
+        BOOST_TEST(*it++ == 3);
+        BOOST_TEST(*it++ == 2);
+        BOOST_TEST(*it++ == 1);
+        return;
+    }
+
+    void reverse_copy_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[3];
+        reverse_copy(arg1, arg2)(array, array2);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 2);
+        BOOST_TEST(array[2] == 3);
+
+        BOOST_TEST(array2[0] == 3);
+        BOOST_TEST(array2[1] == 2);
+        BOOST_TEST(array2[2] == 1);
+
+        return;
+    }
+}
+
+int main()
+{
+    copy_test();
+    copy_backward_test();
+    transform_test();
+    replace_test();
+    replace_if_test();
+    replace_copy_test();
+    replace_copy_if_test();
+    fill_test();
+    fill_n_test();
+    generate_test();
+    generate_n_test();
+    remove_test();
+    remove_if_test();
+    remove_copy_test();
+    remove_copy_if_test();
+    unique_test();
+    unique_copy_test();
+    reverse_test();
+    reverse_copy_test();
+    boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/algorithm/transformation2.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/algorithm/transformation2.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,188 @@
+/*=============================================================================
+    Copyright (c) 2005-2007 Dan Marsden
+    Copyright (c) 2005-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)
+==============================================================================*/
+
+#include <boost/spirit/include/phoenix_stl.hpp/transformation.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <list>
+
+namespace
+{
+    struct even
+    {
+        bool operator()(const int i) const
+        {
+            return i % 2 == 0;
+        }
+    };
+
+    void rotate_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        rotate(arg1, array + 1)(array);
+        std::cout << array[0] << array[1] << array[2] << std::endl;
+        BOOST_TEST(array[0] == 2);
+        BOOST_TEST(array[1] == 3);
+        BOOST_TEST(array[2] == 1);
+        
+        return;
+    }
+
+    void rotate_copy_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[3];
+        rotate_copy(arg1, array + 1, arg2)(array, array2);
+        BOOST_TEST(array2[0] == 2);
+        BOOST_TEST(array2[1] == 3);
+        BOOST_TEST(array2[2] == 1);
+        
+        return;
+    }
+
+    void random_shuffle_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        random_shuffle(arg1)(array);
+        const int first = array[0];
+        BOOST_TEST(first == 1 || first == 2 || first == 3);
+        const int second = array[1];
+        BOOST_TEST(second == 1 || second == 2 || second == 3);
+        BOOST_TEST(first != second);
+        const int third = array[2];
+        BOOST_TEST(third == 1 || third == 2 || third == 3);
+        BOOST_TEST(first != third && second != third);
+        return;
+    }
+    
+    void partition_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int* const end = partition(arg1, even())(array);
+        BOOST_TEST(end == array + 1);
+        BOOST_TEST(array[0] % 2 == 0);
+        BOOST_TEST(array[1] % 2 != 0);
+        BOOST_TEST(array[2] % 2 != 0);
+        return;
+    }
+
+    void stable_partition_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int* const end = stable_partition(arg1, even())(array);
+        BOOST_TEST(end == array + 1);
+        BOOST_TEST(array[0] == 2);
+        BOOST_TEST(array[1] == 1);
+        BOOST_TEST(array[2] == 3);
+        return;
+    }
+
+    void sort_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {3,1,2};
+        std::list<int> test_list(array, array + 3);
+        sort(arg1)(array);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 2);
+        BOOST_TEST(array[2] == 3);
+
+        sort(arg1)(test_list);
+        std::list<int>::const_iterator it(test_list.begin());
+        BOOST_TEST(*it++ == 1);
+        BOOST_TEST(*it++ == 2);
+        BOOST_TEST(*it++ == 3);
+
+        boost::phoenix::sort(arg1, std::greater<int>())(array);
+        BOOST_TEST(array[0] == 3);
+        BOOST_TEST(array[1] == 2);
+        BOOST_TEST(array[2] == 1);
+
+        boost::phoenix::sort(arg1, std::greater<int>())(test_list);
+        std::list<int>::const_iterator jt(test_list.begin());
+        BOOST_TEST(*jt++ == 3);
+        BOOST_TEST(*jt++ == 2);
+        BOOST_TEST(*jt++ == 1);
+
+        return;
+    }
+
+    void stable_sort_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {3,1,2};
+        stable_sort(arg1)(array);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 2);
+        BOOST_TEST(array[2] == 3);
+
+        boost::phoenix::stable_sort(arg1, std::greater<int>())(array);
+        BOOST_TEST(array[0] == 3);
+        BOOST_TEST(array[1] == 2);
+        BOOST_TEST(array[2] == 1);
+        
+        return;
+    }
+
+    void partial_sort_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {2,4,1,3};
+        partial_sort(arg1, array + 2)(array);
+        BOOST_TEST(array[0] == 1);
+        BOOST_TEST(array[1] == 2);
+
+        boost::phoenix::partial_sort(arg1, array + 2, std::greater<int>())(array);
+        BOOST_TEST(array[0] == 4);
+        BOOST_TEST(array[1] == 3);
+        return;
+    }
+
+    void partial_sort_copy_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {2,4,1,3};
+        int array2[2];
+        partial_sort_copy(arg1, arg2)(array, array2);
+        BOOST_TEST(array2[0] == 1);
+        BOOST_TEST(array2[1] == 2);
+
+        boost::phoenix::partial_sort(arg1, arg2, std::greater<int>())(array, array2);
+        BOOST_TEST(array2[0] == 4);
+        BOOST_TEST(array2[1] == 3);
+        return;
+    }
+}
+
+int main()
+{
+    rotate_test();
+    rotate_copy_test();
+    random_shuffle_test();
+    partition_test();
+    stable_partition_test();
+    sort_test();
+    stable_sort_test();
+    partial_sort_test();
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/algorithm/transformation3.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/algorithm/transformation3.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,176 @@
+/*=============================================================================
+    Copyright (c) 2005-2007 Dan Marsden
+    Copyright (c) 2005-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)
+==============================================================================*/
+
+#include <boost/spirit/phoenix/stl/algorithm/transformation.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <list>
+
+namespace
+{
+    void nth_element_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {5,1,4,3,2};
+        nth_element(arg1, array + 2)(array);
+        BOOST_TEST(array[0] < 3);
+        BOOST_TEST(array[1] < 3);
+        BOOST_TEST(array[2] == 3);
+        BOOST_TEST(array[3] > 3);
+        BOOST_TEST(array[4] > 3);
+
+        boost::phoenix::nth_element(arg1, array + 2, std::greater<int>())(array);
+        BOOST_TEST(array[0] > 3);
+        BOOST_TEST(array[1] > 3);
+        BOOST_TEST(array[2] == 3);
+        BOOST_TEST(array[3] < 3);
+        BOOST_TEST(array[4] < 3);
+
+        return;
+    }
+
+    void merge_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[] = {2,3,4};
+        int output[6];
+
+        BOOST_TEST(merge(arg1, arg2, arg3)(array, array2, output) == output + 6);
+        int expected_result[] = {1,2,2,3,3,4};
+        BOOST_TEST(std::equal(output, output + 6, expected_result));
+
+        int array3[] = {5,4,3};
+        int array4[] = {3,2,1};
+        int output2[6];
+        BOOST_TEST(boost::phoenix::merge(arg1, arg2, arg3, std::greater<int>())(array3, array4, output2) ==
+                   output2 + 6);
+        int expected_result2[] = {5,4,3,3,2,1};
+        BOOST_TEST(std::equal(output2, output2 + 6, expected_result2));
+        return;
+    }
+
+    void inplace_merge_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3,2,3,4};
+        inplace_merge(arg1, array + 3)(array);
+        int expected_result[] = {1,2,2,3,3,4};
+        BOOST_TEST(std::equal(array, array + 6, expected_result));
+
+        int array2[] = {5,4,3,4,3,2};
+        boost::phoenix::inplace_merge(arg1, array2 + 3, std::greater<int>())(array2);
+        int expected_result2[] = {5,4,4,3,3,2};
+        BOOST_TEST(std::equal(array2, array2 + 6, expected_result2));
+        return;
+    }
+
+    void set_union_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[] = {2,3,4};
+        int output[4];
+        BOOST_TEST(set_union(arg1, arg2, arg3)(array, array2, output) == output + 4);
+        int expected_result[] = {1,2,3,4};
+        BOOST_TEST(std::equal(output, output + 4, expected_result));
+
+        int array3[] = {3,2,1};
+        int array4[] = {4,3,2};
+        int output2[4];
+        BOOST_TEST(boost::phoenix::set_union(arg1, arg2, arg3, std::greater<int>())
+                   (array3, array4, output2) == 
+                   output2 + 4);
+        int expected_result2[] = {4,3,2,1};
+        BOOST_TEST(std::equal(output2, output2 + 4, expected_result2));
+        return;
+    }
+
+    void set_intersection_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[] = {2,3,4};
+        int output[2];
+        BOOST_TEST(set_intersection(arg1, arg2, arg3)(array, array2, output) == output + 2);
+        int expected_result[] = {2,3};
+        BOOST_TEST(std::equal(output, output + 2, expected_result));
+
+        int array3[] = {3,2,1};
+        int array4[] = {4,3,2};
+        int output2[2];
+        BOOST_TEST(boost::phoenix::set_intersection(arg1, arg2, arg3, std::greater<int>())
+                   (array3, array4, output2) == 
+                   output2 + 2);
+        int expected_result2[] = {3,2};
+        BOOST_TEST(std::equal(output2, output2 + 2, expected_result2));
+        return;
+    }
+
+    void set_difference_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[] = {2,3,4};
+        int output[1];
+        BOOST_TEST(set_difference(arg1, arg2, arg3)(array, array2, output) == output + 1);
+        int expected_result[] = {1};
+        BOOST_TEST(std::equal(output, output + 1, expected_result));
+
+        int array3[] = {3,2,1};
+        int array4[] = {4,3,2};
+        int output2[1];
+        BOOST_TEST(boost::phoenix::set_difference(arg1, arg2, arg3, std::greater<int>())
+                   (array3, array4, output2) == 
+                   output2 + 1);
+        int expected_result2[] = {1};
+        BOOST_TEST(std::equal(output2, output2 + 1, expected_result2));
+        return;
+    }
+
+    void set_symmetric_difference_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int array2[] = {2,3,4};
+        int output[2];
+        BOOST_TEST(set_symmetric_difference(arg1, arg2, arg3)(array, array2, output) == output + 2);
+        int expected_result[] = {1,4};
+        BOOST_TEST(std::equal(output, output + 2, expected_result));
+
+        int array3[] = {3,2,1};
+        int array4[] = {4,3,2};
+        int output2[2];
+        BOOST_TEST(boost::phoenix::set_symmetric_difference(arg1, arg2, arg3, std::greater<int>())
+                   (array3, array4, output2) == 
+                   output2 + 2);
+        int expected_result2[] = {4,1};
+        BOOST_TEST(std::equal(output2, output2 + 2, expected_result2));
+        return;
+    }
+}
+
+int main()
+{
+    nth_element_test();
+    merge_test();
+    inplace_merge_test();
+    set_union_test();
+    set_intersection_test();
+    set_difference_test();
+    set_symmetric_difference_test();
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/algorithm/transformation4.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/algorithm/transformation4.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,153 @@
+/*=============================================================================
+    Copyright (c) 2005-2007 Dan Marsden
+    Copyright (c) 2005-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)
+==============================================================================*/
+
+#include <boost/spirit/phoenix/stl/algorithm/transformation.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <vector>
+#include <functional>
+#include <algorithm>
+
+namespace
+{
+    void heap_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        std::vector<int> vec(array, array + 3);
+        boost::phoenix::make_heap(arg1)(vec);
+        vec.push_back(5);
+        boost::phoenix::push_heap(arg1)(vec);
+        vec.push_back(4);
+        boost::phoenix::push_heap(arg1)(vec);
+        boost::phoenix::pop_heap(arg1)(vec);
+        BOOST_TEST(vec.back() == 5);
+        vec.pop_back();
+        boost::phoenix::sort_heap(arg1)(vec);
+        int expected_result[] = {1,2,3,4};
+        BOOST_TEST(std::equal(vec.begin(), vec.end(), expected_result));
+
+        int array2[] = {3,2,1};
+        std::vector<int> vec2(array2, array2 + 3);
+        boost::phoenix::make_heap(arg1, std::greater<int>())(vec2);
+        vec2.push_back(5);
+        boost::phoenix::push_heap(arg1, std::greater<int>())(vec2);
+        vec2.push_back(4);
+        boost::phoenix::push_heap(arg1, std::greater<int>())(vec2);
+        boost::phoenix::pop_heap(arg1, std::greater<int>())(vec2);
+        BOOST_TEST(vec2.back() == 1);
+        vec2.pop_back();
+        boost::phoenix::sort_heap(arg1, std::greater<int>())(vec2);
+        int expected_result2[] = {5,4,3,2};
+        BOOST_TEST(std::equal(vec2.begin(), vec2.end(), expected_result2));
+
+        return;
+    }
+
+    void next_permutation_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2};
+        int expected_result[] = {2,1};
+        int expected_result2[] = {1,2};
+
+        BOOST_TEST(next_permutation(arg1)(array));
+        BOOST_TEST(std::equal(array, array + 2, expected_result));
+        BOOST_TEST(!next_permutation(arg1)(array));
+        BOOST_TEST(std::equal(array, array + 2, expected_result2));
+
+        std::reverse(array, array + 2);
+        BOOST_TEST(boost::phoenix::next_permutation(arg1, std::greater<int>())(array));
+        BOOST_TEST(std::equal(array, array + 2, expected_result2));
+        BOOST_TEST(!boost::phoenix::next_permutation(arg1, std::greater<int>())(array));
+        BOOST_TEST(std::equal(array, array + 2, expected_result));
+        return;
+    }
+
+    void prev_permutation_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {2,1};
+        int expected_result[] = {1,2};
+        int expected_result2[] = {2,1};
+
+        BOOST_TEST(prev_permutation(arg1)(array));
+        BOOST_TEST(std::equal(array, array + 2, expected_result));
+        BOOST_TEST(!prev_permutation(arg1)(array));
+        BOOST_TEST(std::equal(array, array + 2, expected_result2));
+
+        std::reverse(array, array + 2);
+        BOOST_TEST(boost::phoenix::prev_permutation(arg1, std::greater<int>())(array));
+        BOOST_TEST(std::equal(array, array + 2, expected_result2));
+        BOOST_TEST(!boost::phoenix::prev_permutation(arg1, std::greater<int>())(array));
+        BOOST_TEST(std::equal(array, array + 2, expected_result));
+        return;
+    }
+
+    void inner_product_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int lhs[] = {1,2,3};
+        int rhs[] = {4,5,6};
+        BOOST_TEST(inner_product(arg1, arg2, 0)
+                   (lhs, rhs) == 1*4 + 2*5 + 3*6);
+        BOOST_TEST(boost::phoenix::inner_product(arg1, arg2, 1, std::multiplies<int>(), std::minus<int>())
+                   (lhs, rhs) == (1 - 4) * (2 - 5) * (3 - 6));
+        return;
+    }
+
+    void partial_sum_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int output[3];
+        BOOST_TEST(partial_sum(arg1, arg2)(array, output) == output + 3);
+        int expected_result[] = {1, 3, 6};
+        BOOST_TEST(std::equal(output, output + 3, expected_result));
+
+        BOOST_TEST(boost::phoenix::partial_sum(arg1, arg2, std::multiplies<int>())
+                   (array, output) == output + 3);
+        int expected_result2[] = {1, 2, 6};
+        BOOST_TEST(std::equal(output, output + 3, expected_result2));
+        return;
+    }
+
+    void adjacent_difference_test()
+    {
+        using namespace boost::phoenix;
+        using namespace boost::phoenix::arg_names;
+        int array[] = {1,2,3};
+        int output[3];
+        BOOST_TEST(adjacent_difference(arg1, arg2)(array, output) == output + 3);
+        int expected_result[] = {1, 1, 1};
+        BOOST_TEST(std::equal(output, output + 3, expected_result));
+        BOOST_TEST(boost::phoenix::adjacent_difference(arg1, arg2, std::plus<int>())
+                   (array, output) == output + 3);
+        int expected_result2[] = {1, 3, 5};
+        BOOST_TEST(std::equal(output, output + 3, expected_result2));
+        return;
+    }
+
+}
+
+int main()
+{
+    heap_test();
+    next_permutation_test();
+    prev_permutation_test();
+    inner_product_test();
+    partial_sum_test();
+    adjacent_difference_test();
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/bind/bind_function_object_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/bind/bind_function_object_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,106 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <cmath>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_bind.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+    struct test
+    {
+        typedef void result_type;
+        void operator()() const
+        {
+            cout << "Test lazy functions...\n";
+        }
+    };
+
+    struct sqr
+    {
+        template <typename Arg>
+        struct result
+        {
+            typedef Arg type;
+        };
+
+        template <typename Arg>
+        Arg operator()(Arg n) const
+        {
+            return n * n;
+        }
+    };
+
+    struct fact
+    {
+        template <typename Arg>
+        struct result
+        {
+            typedef Arg type;
+        };
+
+        template <typename Arg>
+        Arg operator()(Arg n) const
+        {
+            return (n <= 0) ? 1 : n * (*this)(n-1);
+        }
+    };
+
+    struct power
+    {
+        template <typename Arg1, typename Arg2>
+        struct result
+        {
+            typedef Arg1 type;
+        };
+
+        template <typename Arg1, typename Arg2>
+        Arg1 operator()(Arg1 a, Arg2 b) const
+        {
+            return pow(a, b);
+        }
+    };
+
+    struct add
+    {
+        template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+        struct result
+        {
+            typedef Arg1 type;
+        };
+
+        template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+        Arg1 operator()(Arg1 a, Arg2 b, Arg3 c, Arg4 d) const
+        {
+            return a + b + c + d;
+        }
+    };
+
+int
+main()
+{
+    int i5 = 5;
+    double d5 = 5, d3 = 3;
+
+    test()();
+    BOOST_TEST(bind(sqr(), arg1)(i5) == (i5*i5));
+    BOOST_TEST(bind(fact(), 4)() == 24);
+    BOOST_TEST(bind(fact(), arg1)(i5) == 120);
+    BOOST_TEST((int)bind(power(), arg1, arg2)(d5, d3) == (int)pow(d5, d3));
+    BOOST_TEST((bind(sqr(), arg1) + 5)(i5) == ((i5*i5)+5));
+    BOOST_TEST(bind(add(), arg1, arg1, arg1, arg1)(i5) == (5+5+5+5));
+
+    int const ic5 = 5;
+    // testing consts
+    BOOST_TEST(bind(sqr(), arg1)(ic5) == (ic5*ic5));
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/bind/bind_function_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/bind/bind_function_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,57 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <cmath>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_bind.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+namespace test
+{
+    void
+    test()
+    {
+        cout << "Test binding functions...\n";
+    }
+
+    int
+    negate(int n)
+    {
+        return -n;
+    }
+
+    int
+    plus(int a, int b)
+    {
+        return a + b;
+    }
+
+    int
+    plus4(int a, int b, int c, int d)
+    {
+        return a + b + c + d;
+    }
+}
+
+int
+main()
+{
+    int a = 123;
+    int b = 256;
+
+    bind(test::test)();
+    BOOST_TEST(bind(test::negate, arg1)(a) == -a);
+    BOOST_TEST(bind(test::plus, arg1, arg2)(a, b) == a+b);
+    BOOST_TEST(bind(test::plus4, arg1, arg2, 3, 4)(a, b) == a+b+3+4);
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/bind/bind_member_function_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/bind/bind_member_function_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,76 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <cmath>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_bind.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+namespace phx = boost::phoenix;
+
+namespace test
+{
+    struct x : boost::noncopyable // test non-copyable (hold this by reference)
+    {
+        void
+        test() const
+        {
+            cout << "Test binding member functions...\n";
+        }
+    };
+
+    struct y : boost::noncopyable // test non-copyable (hold this by reference)
+    {
+        int
+        negate(int n)
+        {
+            return -n;
+        }
+    };
+
+    struct z : boost::noncopyable // test non-copyable (hold this by reference)
+    {
+        int
+        plus(int a, int b)
+        {
+            return a + b;
+        }
+    };
+
+    struct zz : boost::noncopyable // test non-copyable (hold this by reference)
+    {
+        int
+        plus3(int a, int b, int c)
+        {
+            return a + b + c;
+        }
+    };
+}
+
+int
+main()
+{
+    int a = 123;
+    int b = 256;
+    test::x x_;
+    test::y y_;
+    test::z z_;
+    test::zz zz_;
+
+    bind(&test::x::test, x_)();
+    BOOST_TEST(bind(&test::y::negate, y_, arg1)(a) == -a);
+    BOOST_TEST(bind(&test::z::plus, arg1, arg2, arg3)(z_, a, b) == a+b);
+    BOOST_TEST(bind(&test::zz::plus3, zz_, arg1, arg2, arg3)(a, b, a) == a+b+a);
+    BOOST_TEST(bind(&test::y::negate, &y_, 777)(a) == -777);
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/bind/bind_member_variable_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/bind/bind_member_variable_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,37 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <cmath>
+#include <boost/noncopyable.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_bind.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+namespace phx = boost::phoenix;
+
+namespace test
+{
+    struct x : boost::noncopyable // test non-copyable (hold this by reference)
+    {
+        int m;
+    };
+}
+
+int
+main()
+{
+    test::x x_;
+    bind(&test::x::m, x_)() = 123;
+    bind(&test::x::m, arg1)(x_) = 123;
+    BOOST_TEST(x_.m == 123);
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/container/container_tests.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,814 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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(CONTAINER_TESTS_HPP)
+#define CONTAINER_TESTS_HPP
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/phoenix/stl/container/container.hpp>
+
+#include <iostream>
+#include <typeinfo>
+#include <deque>
+#include <list>
+#include <map>
+#include <vector>
+#include <utility>
+
+#ifdef BOOST_MSVC
+#pragma warning(disable : 4800)
+#endif
+
+using std::cerr;
+namespace phx = boost::phoenix;
+
+std::deque<int> const build_deque();
+std::list<int> const build_list();
+std::map<int, int> const build_map();
+std::multimap<int, int> const build_multimap();
+std::vector<int> const build_vector();
+
+inline bool
+test(bool fail)
+{
+    BOOST_TEST(!fail);
+    return fail;
+}
+
+template <typename Container>
+void test_assign(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::assign;
+
+    typename Container::size_type count = 2;
+    typename Container::const_iterator first = c.begin();
+    typename Container::const_iterator second = first;
+    typename Container::value_type value = *first;
+
+    assign(arg1, count, value)(c);
+
+    // iterators may be invalidated!
+    first = c.begin();
+    second = first;
+
+    std::advance(second, 1);
+    if (test(*first != *second)) {
+        cerr << "Failed " << typeid(Container).name() << " test_assign 1\n";
+        return;
+    }
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    Container const const_c = c;
+    assign(const_c, count, value);
+#endif
+}
+
+template <typename Container>
+void test_assign2(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::arg_names::arg2;
+    using phx::arg_names::arg3;
+    using phx::assign;
+
+    Container c2 = c;
+    typename Container::const_iterator first = c2.begin();
+    typename Container::const_iterator last = c2.end();
+    typename Container::size_type size = c2.size();
+
+    c.clear();
+    assign(arg1, arg2, arg3)(c, first, last);
+    if (test(c.size() != size)) {
+        cerr << "Failed " << typeid(Container).name()
+	     << " test_assign2 1\n"
+	     << "size == " << c.size() << '\n';
+        return;
+    }
+
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    Container const const_c = c;
+    assign(const_c, first, second);
+#endif
+}
+
+template <typename Container>
+void test_at(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::at;
+
+    typename Container::reference r1 = at(arg1, 0)(c);
+    if (test(r1 != c.at(0))) {
+        cerr << "Failed " << typeid(Container).name() << " test_at 1\n";
+        return;
+    }
+
+    typename Container::const_reference r2 = at(arg1, 0)(c);
+    if (test(r2 != c.at(0))) {
+        cerr << "Failed " << typeid(Container).name() << " test_at 2\n";
+        return;
+    }
+
+    Container const const_c = c;
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    typename Container::reference r3 = at(arg1, 0)(const_c);
+#endif
+
+    typename Container::const_reference r4 = at(arg1, 0)(const_c);
+    if (test(r4 != c.at(0))) {
+        cerr << "Failed " << typeid(Container).name() << " test_at 4\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_back(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::back;
+
+    typename Container::reference r1 = back(arg1)(c);
+    if (test(r1 != c.back())) {
+        cerr << "Failed " << typeid(Container).name() << " test_back 1\n";
+        return;
+    }
+    typename Container::const_reference r2 = back(arg1)(c);
+    if (test(r2 != c.back())) {
+        cerr << "Failed " << typeid(Container).name() << " test_back 2\n";
+        return;
+    }
+
+    Container const const_c = c;
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    typename Container::reference r3 = back(arg1)(const_c);
+#endif
+
+    typename Container::const_reference r4 = back(arg1)(const_c);
+    if (test(r4 != c.back())) {
+        cerr << "Failed " << typeid(Container).name() << " test_back 4\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_begin(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::begin;
+
+    typename Container::iterator it1 = begin(arg1)(c);
+    if (test(it1 != c.begin())) {
+        cerr << "Failed " << typeid(Container).name() << " test_begin 1\n";
+        return;
+    }
+    typename Container::const_iterator it2 = begin(arg1)(c);
+    if (test(it2 != c.begin())) {
+        cerr << "Failed " << typeid(Container).name() << " test_begin 2\n";
+        return;
+    }
+
+    Container const const_c = c;
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    typename Container::iterator it3 = begin(arg1)(const_c);
+#endif
+
+    typename Container::const_iterator it4 = begin(arg1)(const_c);
+    if (test(it4 != const_c.begin())) {
+        cerr << "Failed " << typeid(Container).name() << " test_begin 4\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_capacity(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::capacity;
+
+    typename Container::size_type s1 = capacity(arg1)(c);
+    if (test(s1 != c.capacity())) {
+        cerr << "Failed " << typeid(Container).name() << " test_capacity 1\n";
+        return;
+    }
+
+    Container const const_c = c;
+    typename Container::size_type s2 = capacity(arg1)(const_c);
+    if (test(s2 != const_c.capacity())) {
+        cerr << "Failed " << typeid(Container).name() << " test_capacity 2\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_clear(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::clear;
+
+    clear(arg1)(c);
+    if (test(!c.empty())) {
+        cerr << "Failed " << typeid(Container).name() << " test_clear 1\n";
+        return;
+    }
+
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    Container const const_c = c;
+    clear(arg1)(const_c);
+#endif
+}
+
+template <typename Container>
+void test_empty(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::empty;
+
+    typename Container::size_type s1 = empty(arg1)(c);
+    if (test(bool(s1) != c.empty())) {
+        cerr << "Failed " << typeid(Container).name() << " test_empty 1\n";
+        return;
+    }
+
+    Container const const_c = c;
+    typename Container::size_type s2 = empty(arg1)(const_c);
+    if (test(bool(s2) != const_c.empty())) {
+        cerr << "Failed " << typeid(Container).name() << " test_empty 2\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_end(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::end;
+
+    typename Container::iterator it1 = end(arg1)(c);
+    if (test(it1 != c.end())) {
+        cerr << "Failed " << typeid(Container).name() << " test_end 1\n";
+        return;
+    }
+    typename Container::const_iterator it2 = end(arg1)(c);
+    if (test(it2 != c.end())) {
+        cerr << "Failed " << typeid(Container).name() << " test_end 2\n";
+        return;
+    }
+
+    Container const const_c = c;
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    typename Container::iterator it3 = end(arg1)(const_c);
+#endif
+
+    typename Container::const_iterator it4 = end(arg1)(const_c);
+    if (test(it4 != const_c.end())) {
+        cerr << "Failed " << typeid(Container).name() << " test_end 4\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_erase(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::arg_names::arg2;
+    using phx::arg_names::arg3;
+    using phx::erase;
+
+    Container const const_c = c;
+
+    typename Container::size_type size = c.size();
+    typename Container::iterator c_begin = c.begin();
+    erase(arg1, arg2)(c, c_begin);
+    if (test(c.size() + 1 != size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_erase 1\n";
+        return;
+    }
+
+    c_begin = c.begin();
+    typename Container::iterator c_end = c.end();
+    erase(arg1, arg2, arg3)(c, c_begin, c_end);
+    if (test(!c.empty())) {
+        cerr << "Failed " << typeid(Container).name() << " test_erase 2\n";
+        return;
+    }
+
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    erase(arg1, const_c.begin())(const_c);
+    erase(arg1, const_c.begin(), const_c.end())(const_c);
+#endif
+}
+
+template <typename Container>
+void test_map_erase(Container c)
+{
+    test_erase(c);
+    if (boost::report_errors() != 0)
+	    return;
+
+    using phx::arg_names::arg1;
+    using phx::arg_names::arg2;
+    using phx::erase;
+
+    typename Container::value_type const value = *c.begin();
+    typename Container::key_type const key = value.first;
+    typename Container::size_type const removed =
+	    erase(arg1, arg2)(c, key);
+    if (test(removed != 1)) {
+        cerr << "Failed " << typeid(Container).name() << " test_map_erase 1\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_front(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::front;
+
+    typename Container::reference r1 = front(arg1)(c);
+    if (test(r1 != c.front())) {
+        cerr << "Failed " << typeid(Container).name() << " test_front 1\n";
+        return;
+    }
+    typename Container::const_reference r2 = front(arg1)(c);
+    if (test(r2 != c.front())) {
+        cerr << "Failed " << typeid(Container).name() << " test_front 2\n";
+        return;
+    }
+
+    Container const const_c = c;
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    typename Container::reference r3 = front(arg1)(const_c);
+#endif
+
+    typename Container::const_reference r4 = front(arg1)(const_c);
+    if (test(r4 != c.front())) {
+        cerr << "Failed " << typeid(Container).name() << " test_front 4\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_get_allocator(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::get_allocator;
+
+    Container const const_c = c;
+
+    typename Container::allocator_type a1 = get_allocator(arg1)(c);
+    if (test(a1 != c.get_allocator())) {
+        cerr << "Failed " << typeid(Container).name() << " test_get_allocator 1\n";
+        return;
+    }
+
+    typename Container::allocator_type a2 = get_allocator(arg1)(const_c);
+    if (test(a2 != const_c.get_allocator())) {
+        cerr << "Failed " << typeid(Container).name() << " test_get_allocator 2\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_insert(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::insert;
+
+    typename Container::value_type const value = *c.begin();
+    typename Container::iterator it = insert(arg1, c.begin(), value)(c);
+    if (test(it != c.begin() || *it != *(++it))) {
+        cerr << "Failed " << typeid(Container).name() << " test_insert 1\n";
+        return;
+    }
+
+    typename Container::size_type size = c.size();
+    insert(arg1, c.begin(), 3, value)(c);
+    if (test(c.size() != size + 3)) {
+        cerr << "Failed " << typeid(Container).name() << " test_insert 2\n";
+        return;
+    }
+
+    Container const const_c = c;
+    size = c.size();
+    insert(arg1, c.begin(), const_c.begin(), const_c.end())(c);
+    if (test(c.size() != 2 * size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_insert 3\n";
+        return;
+    }
+}
+
+inline void test_map_insert(std::map<int, int> c)
+{
+    using phx::arg_names::arg1;
+    using phx::arg_names::arg2;
+    using phx::arg_names::arg3;
+
+    typedef std::map<int, int> Map;
+
+    Map::value_type const value = *c.begin();
+    Map::iterator c_begin = c.begin();
+    // wrapper for
+    // iterator insert(iterator where, const value_type& val);
+    Map::iterator it =
+        phx::insert(arg1, arg2, arg3)(c, c_begin, value);
+
+    if (test(it != c.begin() /*|| *it != *(++it)*/)) {
+        cerr << "Failed " << typeid(Map).name() << " test_map_insert 1\n";
+        return;
+    }
+
+    // wrapper for
+    // pair<iterator, bool> insert(const value_type& val);
+    Map::value_type const value2(1400, 2200);
+    std::pair<Map::iterator, bool> result =
+	    phx::insert(arg1, arg2)(c, value2);
+    if (test(!result.second)) {
+        cerr << "Failed " << typeid(Map).name() << " test_map_insert 2\n";
+        return;
+    }
+
+    // wrapper for
+    // template<class InIt>
+    // void insert(InIt first, InIt last);
+    Map const const_c = build_map();
+    Map::size_type size = c.size();
+    phx::insert(arg1, const_c.begin(), const_c.end())(c);
+    if (test(c.size() != size + const_c.size())) {
+        cerr << "Failed " << typeid(Map).name() << " test_map_insert 3\n";
+        return;
+    }
+}
+
+inline void test_multimap_insert(std::multimap<int, int> c)
+{
+    using phx::arg_names::arg1;
+    using phx::arg_names::arg2;
+    using phx::arg_names::arg3;
+
+    typedef std::multimap<int, int> Multimap;
+
+    Multimap::value_type const value = *c.begin();
+    Multimap::iterator c_begin = c.begin();
+    // wrapper for
+    // iterator insert(iterator where, const value_type& val);
+    Multimap::iterator it =
+        phx::insert(arg1, arg2, arg3)(c, c_begin, value);
+
+    if (test(it != c.begin() || *it != *(++it))) {
+        cerr << "Failed " << typeid(Multimap).name()
+	     << " test_multimap_insert 1\n";
+        return;
+    }
+
+    // wrapper for
+    // iterator insert(const value_type& val);
+    Multimap::value_type const value2(1400, 2200);
+    it = phx::insert(arg1, arg2)(c, value2);
+    if (test(it == c.end())) {
+        cerr << "Failed " << typeid(Multimap).name()
+	     << " test_multimap_insert 2\n";
+        return;
+    }
+
+    // wrapper for
+    // template<class InIt>
+    // void insert(InIt first, InIt last);
+    Multimap const const_c = build_multimap();
+    Multimap::size_type size = c.size();
+    phx::insert(arg1, const_c.begin(), const_c.end())(c);
+    if (test(c.size() != size + const_c.size())) {
+        cerr << "Failed " << typeid(Multimap).name()
+	     << " test_multimap_insert 3\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_key_comp(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::key_comp;
+
+    typename Container::key_compare comp = key_comp(arg1)(c);
+
+    Container const const_c = c;
+    comp = key_comp(arg1)(const_c);
+}
+
+template <typename Container>
+void test_max_size(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::max_size;
+
+    Container const const_c = c;
+
+    typename Container::size_type s1 = max_size(arg1)(c);
+    if (test(s1 != c.max_size())) {
+        cerr << "Failed " << typeid(Container).name() << " test_max_size 1\n";
+        return;
+    }
+
+    typename Container::size_type s2 = max_size(arg1)(const_c);
+    if (test(s2 != const_c.max_size())) {
+        cerr << "Failed " << typeid(Container).name() << " test_max_size 2\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_pop_back(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::pop_back;
+
+    Container const const_c = c;
+
+    typename Container::size_type size = c.size();
+
+    pop_back(arg1)(c);
+    if (test(c.size() + 1 != size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_pop_back 1\n";
+        return;
+    }
+
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    pop_back(arg1)(const_c);
+#endif
+}
+
+template <typename Container>
+void test_pop_front(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::pop_front;
+
+    Container const const_c = c;
+
+    typename Container::size_type size = c.size();
+
+    pop_front(arg1)(c);
+    if (test(c.size() + 1 != size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_pop_front 1\n";
+        return;
+    }
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    pop_front(arg1)(const_c);
+#endif
+}
+
+template <typename Container>
+void test_push_back(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::arg_names::arg2;
+    using phx::push_back;
+
+    Container const const_c = c;
+
+    typename Container::value_type data = *c.begin();
+    typename Container::size_type size = c.size();
+    push_back(arg1, arg2)(c, data);
+    if (test(c.size() != size + 1)) {
+        cerr << "Failed " << typeid(Container).name() << " test_push_back 1\n";
+        return;
+    }
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    push_back(arg1, arg2)(const_c, data);
+#endif
+}
+
+template <typename Container>
+void test_push_front(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::arg_names::arg2;
+    using phx::push_front;
+
+    Container const const_c = c;
+
+    typename Container::value_type data = *c.begin();
+    typename Container::size_type size = c.size();
+    push_front(arg1, arg2)(c, data);
+    if (test(c.size() != size + 1)) {
+        cerr << "Failed " << typeid(Container).name() << " test_push_front 1\n";
+        return;
+    }
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    push_front(arg1, arg2)(const_c, data);
+#endif
+}
+
+template <typename Container>
+void test_rbegin(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::rbegin;
+
+    typename Container::reverse_iterator it1 = rbegin(arg1)(c);
+    typename Container::reverse_iterator it1_test = c.rbegin();
+    if (test(it1 != it1_test)) {
+        cerr << "Failed " << typeid(Container).name() << " test_rbegin 1\n";
+        return;
+    }
+    typename Container::const_reverse_iterator it2 = rbegin(arg1)(c);
+    typename Container::const_reverse_iterator it2_test = c.rbegin();
+    if (test(it2 != it2_test)) {
+        cerr << "Failed " << typeid(Container).name() << " test_rbegin 2\n";
+        return;
+    }
+
+    Container const const_c = c;
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    typename Container::reverse_iterator it3 = rbegin(arg1)(const_c);
+#endif
+
+    typename Container::const_reverse_iterator it4 = rbegin(arg1)(const_c);
+    it2_test = const_c.rbegin();
+    if (test(it4 != it2_test)) {
+        cerr << "Failed " << typeid(Container).name() << " test_rbegin 4\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_rend(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::rend;
+
+    typename Container::reverse_iterator it1 = rend(arg1)(c);
+    typename Container::reverse_iterator it1_test = c.rend();
+    if (test(it1 != it1_test)) {
+        cerr << "Failed " << typeid(Container).name() << " test_rend 1\n";
+        return;
+    }
+    typename Container::const_reverse_iterator it2 = rend(arg1)(c);
+    typename Container::const_reverse_iterator it2_test = c.rend();
+    if (test(it2 != it2_test)) {
+        cerr << "Failed " << typeid(Container).name() << " test_rend 2\n";
+        return;
+    }
+
+    Container const const_c = c;
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    // Should not --- does not, Yay! --- compile.
+    typename Container::reverse_iterator it3 = rend(arg1)(const_c);
+#endif
+
+    typename Container::const_reverse_iterator it4 = rend(arg1)(const_c);
+    it2_test = const_c.rend();
+    if (test(it4 != it2_test)) {
+        cerr << "Failed " << typeid(Container).name() << " test_rend 4\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_reserve(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::reserve;
+
+    Container const const_c = c;
+
+    typename Container::size_type count = 2 * c.size();
+    reserve(arg1, count)(c);
+    if (test(c.capacity() < count)) {
+        cerr << "Failed " << typeid(Container).name() << " test_reserve 1\n";
+        return;
+    }
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    reserve(arg1, count)(const_c)(const_c);
+#endif
+}
+
+template <typename Container>
+void test_resize(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::resize;
+
+    Container const const_c = c;
+
+    typename Container::size_type new_size = 2 * c.size();
+    resize(arg1, new_size)(c);
+    if (test(c.size() != new_size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_resize 1\n";
+        return;
+    }
+
+    new_size = 2 * c.size();
+    typename Container::value_type value = *c.begin();
+    resize(arg1, new_size, value)(c);
+    if (test(c.size() != new_size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_resize 2\n";
+        return;
+    }
+#if defined(BOOST_PHOENIX_COMPILE_FAIL_TEST)
+    new_size = 2 * const_c.size();
+    resize(arg1, new_size)(const_c);
+
+    new_size = 2 * const_c.size();
+    resize(arg1, new_size, value)(const_c);
+#endif
+}
+
+template <typename Container>
+void test_size(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::size;
+
+    Container const const_c = c;
+
+    typename Container::size_type s1 = size(arg1)(c);
+    if (test(s1 != c.size())) {
+        cerr << "Failed " << typeid(Container).name() << " test_size 1\n";
+        return;
+    }
+
+    typename Container::size_type s2 = size(arg1)(const_c);
+    if (test(s2 != const_c.size())) {
+        cerr << "Failed " << typeid(Container).name() << " test_size 2\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_splice(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::arg_names::arg2;
+    using phx::arg_names::arg3;
+    using phx::arg_names::arg4;
+    using phx::arg_names::arg5;
+    using phx::splice;
+
+    typename Container::iterator c_end;
+    typename Container::iterator c2_begin;
+    typename Container::iterator c2_end;
+    typename Container::size_type size = c.size();
+
+    Container const copy = c;
+    Container const copy2 = build_list();
+    Container c2 = copy2;
+
+    size = c.size();
+    c_end = c.end();
+    splice(arg1, arg2, arg3)(c, c_end, c2);
+    if (test(c.size() != 2 * size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_splice 1\n";
+        return;
+    }
+
+    c = copy;
+    c_end = c.end();
+    c2 = copy2;
+    c2_begin = c2.begin();
+    size = c.size() + 1;
+    splice(arg1, arg2, arg3, arg4)(c, c_end, c2, c2_begin);
+    if (test(c.size() != size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_splice 2\n";
+        return;
+    }
+
+    c = copy;
+    c_end = c.end();
+    c2 = copy2;
+    c2_begin = c2.begin();
+    c2_end = c2.end();
+    size = c.size() + c2.size();
+    splice(arg1, arg2, arg3, arg4, arg5)(c, c_end, c2, c2_begin, c2_end);
+    if (test(c.size() != size)) {
+        cerr << "Failed " << typeid(Container).name() << " test_splice 3\n";
+        return;
+    }
+}
+
+template <typename Container>
+void test_value_comp(Container c)
+{
+    using phx::arg_names::arg1;
+    using phx::value_comp;
+
+    typename Container::value_compare comp = value_comp(arg1)(c);
+
+    Container const const_c = c;
+    comp = value_comp(arg1)(const_c);
+}
+
+#endif
Added: trunk/libs/spirit/phoenix/test/container/container_tests1a.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests1a.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,46 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+
+std::list<int> const build_list()
+{
+    std::vector<int> const data = build_vector();
+    return std::list<int>(data.begin(), data.end());
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+	    *it += size;
+    return data;
+}
+
+int 
+main()
+{
+    std::list<int> const data = build_list();
+    test_assign(data);
+    test_assign2(data);
+    test_back(data);
+    test_begin(data);
+    test_clear(data);
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests1b.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests1b.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,48 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+
+std::list<int> const build_list()
+{
+    std::vector<int> const data = build_vector();
+    return std::list<int>(data.begin(), data.end());
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int 
+main()
+{
+    std::list<int> const data = build_list();
+    test_empty(data);
+    test_end(data);
+    test_erase(data);
+    test_front(data);
+    test_get_allocator(data);
+    test_insert(data);
+    test_max_size(data);
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests2a.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests2a.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,46 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+
+std::list<int> const build_list()
+{
+    std::vector<int> const data = build_vector();
+    return std::list<int>(data.begin(), data.end());
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int
+main()
+{
+    std::list<int> const data = build_list();
+    test_pop_back(data);
+    test_pop_front(data);
+    test_push_back(data);
+    test_push_front(data);
+    return boost::report_errors();
+}
+
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests2b.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests2b.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,47 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+
+std::list<int> const build_list()
+{
+    std::vector<int> const data = build_vector();
+    return std::list<int>(data.begin(), data.end());
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int
+main()
+{
+    std::list<int> const data = build_list();
+    test_rbegin(data);
+    test_rend(data);
+    test_resize(data);
+    test_size(data);
+    test_splice(data);
+    return boost::report_errors();
+}
+
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests3a.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests3a.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,60 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+#include <boost/static_assert.hpp>
+
+std::map<int, int> const build_map()
+{
+    typedef std::map<int, int> int_map;
+    typedef std::vector<int> int_vector;
+
+    int_map result;
+    int_vector const data = build_vector();
+    int_vector::const_iterator it = data.begin();
+    int_vector::const_iterator const end = data.end();
+    for (; it != end; ++it) {
+	    int const value = *it;
+	    result[value] = 100 * value;
+    }
+    return result;
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+	    *it += size;
+    return data;
+}
+
+int
+main()
+{
+    BOOST_STATIC_ASSERT((phx::stl::has_mapped_type<std::map<int, int> >::value));
+
+    std::map<int, int> const data = build_map();
+    test_begin(data);
+    test_clear(data);
+    test_empty(data);
+    test_end(data);
+    test_map_erase(data);
+    test_get_allocator(data);
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests3b.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests3b.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,61 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+#include <boost/static_assert.hpp>
+
+std::map<int, int> const build_map()
+{
+    typedef std::map<int, int> int_map;
+    typedef std::vector<int> int_vector;
+
+    int_map result;
+    int_vector const data = build_vector();
+    int_vector::const_iterator it = data.begin();
+    int_vector::const_iterator const end = data.end();
+    for (; it != end; ++it) {
+	    int const value = *it;
+	    result[value] = 100 * value;
+    }
+    return result;
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int
+main()
+{
+    BOOST_STATIC_ASSERT((phx::stl::has_mapped_type<std::map<int, int> >::value));
+
+    std::map<int, int> const data = build_map();
+    test_map_insert(data);
+    test_key_comp(data);
+    test_max_size(data);
+    test_rbegin(data);
+    test_rend(data);
+    test_size(data);
+    test_value_comp(data);
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests4a.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests4a.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,47 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+#include <boost/static_assert.hpp>
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int
+main()
+{
+    std::vector<int> const data = build_vector();
+    test_assign(data);
+    test_assign2(data);
+    test_at(data);
+    test_back(data);
+    test_begin(data);
+    test_capacity(data);
+    test_clear(data);
+    test_end(data);
+    test_empty(data);
+    test_erase(data);
+    test_front(data);
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests4b.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests4b.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,46 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+#include <boost/static_assert.hpp>
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int
+main()
+{
+    std::vector<int> const data = build_vector();
+    test_get_allocator(data);
+    test_insert(data);
+    test_max_size(data);
+    test_pop_back(data);
+    test_push_back(data);
+    test_rbegin(data);
+    test_rend(data);
+    test_reserve(data);
+    test_resize(data);
+    test_size(data);
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests5a.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests5a.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,53 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+
+std::deque<int> const build_deque()
+{
+    std::vector<int> const data = build_vector();
+    return std::deque<int>(data.begin(), data.end());
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int
+main()
+{
+    std::deque<int> const data = build_deque();
+    test_assign(data);
+    test_assign2(data);
+    test_at(data);
+    test_back(data);
+    test_begin(data);
+    test_clear(data);
+    test_front(data);
+    test_empty(data);
+    test_end(data);
+    test_erase(data);
+    test_get_allocator(data);
+    return boost::report_errors();
+}
+
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests5b.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests5b.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,52 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+
+std::deque<int> const build_deque()
+{
+    std::vector<int> const data = build_vector();
+    return std::deque<int>(data.begin(), data.end());
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int
+main()
+{
+    std::deque<int> const data = build_deque();
+    test_insert(data);
+    test_max_size(data);
+    test_pop_back(data);
+    test_pop_front(data);
+    test_push_back(data);
+    test_push_front(data);
+    test_rbegin(data);
+    test_rend(data);
+    test_resize(data);
+    test_size(data);
+    return boost::report_errors();
+}
+
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests6a.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests6a.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,69 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+#include <boost/static_assert.hpp>
+
+std::map<int, int> const build_map()
+{
+    typedef std::map<int, int> int_map;
+    typedef std::vector<int> int_vector;
+
+    int_map result;
+    int_vector const data = build_vector();
+    int_vector::const_iterator it = data.begin();
+    int_vector::const_iterator const end = data.end();
+    for (; it != end; ++it) {
+        int const value = *it;
+        result[value] = 100 * value;
+    }
+    return result;
+}
+
+std::multimap<int, int> const build_multimap()
+{
+    typedef std::map<int, int> int_map;
+    typedef std::multimap<int, int> int_multimap;
+    int_map const data = build_map();
+    return int_multimap(data.begin(), data.end());
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+        *it += size;
+    return data;
+}
+
+int
+main()
+{
+    std::multimap<int, int> const data = build_multimap();
+    test_begin(data);
+    test_clear(data);
+    test_empty(data);
+    test_end(data);
+    test_map_erase(data);
+    test_get_allocator(data);
+    return boost::report_errors();
+}
+
+
+
+
Added: trunk/libs/spirit/phoenix/test/container/container_tests6b.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/container/container_tests6b.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,70 @@
+/*=============================================================================
+    Copyright (c) 2004 Angus Leeming
+
+    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 "container_tests.hpp"
+#include <boost/static_assert.hpp>
+
+std::map<int, int> const build_map()
+{
+    typedef std::map<int, int> int_map;
+    typedef std::vector<int> int_vector;
+
+    int_map result;
+    int_vector const data = build_vector();
+    int_vector::const_iterator it = data.begin();
+    int_vector::const_iterator const end = data.end();
+    for (; it != end; ++it) {
+	    int const value = *it;
+	    result[value] = 100 * value;
+    }
+    return result;
+}
+
+std::multimap<int, int> const build_multimap()
+{
+    typedef std::map<int, int> int_map;
+    typedef std::multimap<int, int> int_multimap;
+    int_map const data = build_map();
+    return int_multimap(data.begin(), data.end());
+}
+
+std::vector<int> const init_vector()
+{
+    typedef std::vector<int> int_vector;
+    int const data[] = { -4, -3, -2, -1, 0 };
+    int_vector::size_type const data_size = sizeof(data) / sizeof(data[0]);
+    return int_vector(data, data + data_size);
+}
+
+std::vector<int> const build_vector()
+{
+    typedef std::vector<int> int_vector;
+    static int_vector data = init_vector();
+    int_vector::size_type const size = data.size();
+    int_vector::iterator it = data.begin();
+    int_vector::iterator const end = data.end();
+    for (; it != end; ++it)
+	    *it += size;
+    return data;
+}
+
+int
+main()
+{
+    std::multimap<int, int> const data = build_multimap();
+    test_multimap_insert(data);
+    test_key_comp(data);
+    test_max_size(data);
+    test_rbegin(data);
+    test_rend(data);
+    test_size(data);
+    test_value_comp(data);
+    return boost::report_errors();
+}
+
+
+
+
Added: trunk/libs/spirit/phoenix/test/core/compose_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/core/compose_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,84 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+struct X
+{
+    template <
+        typename Env
+      , typename A0 = void_
+      , typename A1 = void_
+      , typename A2 = void_
+    >
+    struct result
+    {
+        typedef int type;
+    };
+
+    template <typename RT, typename Env
+      , typename A0, typename A1, typename A2>
+    static RT
+    eval(Env const& env, A0& a0, A1& a1, A2& a2)
+    {
+        return a0.eval(env) + a1.eval(env) + a2.eval(env);
+    }
+};
+
+int
+main()
+{
+    using boost::fusion::at_c;
+    {
+        //  testing as_actor
+        BOOST_STATIC_ASSERT((boost::is_same<
+            as_actor<actor<argument<0> > >::type, actor<argument<0> > >::value));
+        BOOST_STATIC_ASSERT((boost::is_same<
+            as_actor<int>::type, actor<value<int> > >::value));
+    }
+
+    {
+        //  testing compose
+        char const* s = "Hi";
+        int x = 123;
+
+        BOOST_TEST(at_c<0>(compose<X>(1, arg1, val(1)))
+            .eval(basic_environment<>()) == 1);
+        BOOST_TEST(at_c<1>(compose<X>(1, arg1, val(456)))
+            .eval(basic_environment<char const*>(s)) == s);
+        BOOST_TEST(at_c<2>(compose<X>(1, arg1, val(456)))
+            .eval(basic_environment<>()) == 456);
+        BOOST_TEST(compose<X>(9876, arg1, val(456))
+            .eval(basic_environment<int>(x)) == 10455);
+
+        //  testing composite sizes
+        cout << "sizeof(arg1) is: "
+            << sizeof(arg1) << endl;
+        cout << "sizeof(compose<X>(arg1)) is: "
+            << sizeof(compose<X>(arg1)) << endl;
+        cout << "sizeof(compose<X>(1, arg1, val(456))) is: "
+            << sizeof(compose<X>(1, arg1, val(456))) << endl;
+        cout << "sizeof(compose<X>()) is: "
+            << sizeof(compose<X>()) << endl;
+        cout << "sizeof(compose<X>('x')) is: "
+            << sizeof(compose<X>('x')) << endl;
+        cout << "sizeof(compose<X>('x', 3)) is: "
+            << sizeof(compose<X>('x', 3)) << endl;
+        cout << "sizeof(compose<X>('x', 'y', 3)) is: "
+            << sizeof(compose<X>('x', 'y', 3)) << endl;
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/core/primitives_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/core/primitives_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,69 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <string>
+
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    char c1 = '1';
+    int i1 = 1, i2 = 2, i = 4;
+    const char* s2 = "2";
+
+    ///////////////////////////////////////////////////////////////////////////
+    //
+    //  Values, references and arguments
+    //
+    ///////////////////////////////////////////////////////////////////////////
+
+    //  argument
+    BOOST_TEST(arg1(c1) == c1);
+    BOOST_TEST(arg1(i1, i2) == i1);
+    BOOST_TEST(arg2(i1, s2) == s2);
+    BOOST_TEST(&(arg1(c1)) == &c1); // must be an lvalue
+
+    //  value
+    cout << val("Hello,")() << val(' ')() << val("World")() << endl;
+    BOOST_TEST(val(3)() == 3);
+    BOOST_TEST(val("Hello, world")() == std::string("Hello, world"));
+    BOOST_TEST(val(_1)(i1) == i1);
+
+    //  should not compile:
+#ifdef PHOENIX_SHOULD_NOT_COMPILE_TEST
+    &val(_1)(i1); // should return an rvalue
+#endif
+
+    //  reference
+    BOOST_TEST(cref(i)() == ref(i)());
+    BOOST_TEST(cref(i)() == 4);
+    BOOST_TEST(i == 4);
+    BOOST_TEST(ref(++i)() == 5);
+    BOOST_TEST(i == 5);    
+
+    //  should not compile:
+#ifdef PHOENIX_SHOULD_NOT_COMPILE_TEST
+    ref(arg1);
+#endif
+
+    // testing consts
+    int const ic = 123;
+    BOOST_TEST(arg1(ic) == 123);
+
+    //  should not compile:
+#ifdef PHOENIX_SHOULD_NOT_COMPILE_TEST
+    arg1();
+#endif
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/detail/type_deduction_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/detail/type_deduction_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,374 @@
+/*=============================================================================
+    Copyright (c) 2001-2003 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/detail/lightweight_test.hpp>
+#include <boost/spirit/home/phoenix/detail/type_deduction.hpp>
+#include <iostream>
+#include <vector>
+#include <map>
+#include <string>
+#include <complex>
+#include <boost/shared_ptr.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+
+namespace boost
+{
+    BOOST_UNARY_RESULT_OF(-x, result_of_negate);
+    BOOST_UNARY_RESULT_OF(+x, result_of_posit);
+    BOOST_UNARY_RESULT_OF(!x, result_of_logical_not);
+    BOOST_UNARY_RESULT_OF(~x, result_of_invert);
+    BOOST_UNARY_RESULT_OF(&x, result_of_reference);
+    BOOST_UNARY_RESULT_OF(*x, result_of_dereference);
+
+    BOOST_UNARY_RESULT_OF(++x, result_of_pre_increment);
+    BOOST_UNARY_RESULT_OF(--x, result_of_pre_decrement);
+    BOOST_UNARY_RESULT_OF(x++, result_of_post_increment);
+    BOOST_UNARY_RESULT_OF(x--, result_of_post_decrement);
+
+    BOOST_BINARY_RESULT_OF(x = y, result_of_assign);
+    BOOST_ASYMMETRIC_BINARY_RESULT_OF(x[y], result_of_index);
+
+    BOOST_BINARY_RESULT_OF(x += y, result_of_plus_assign);
+    BOOST_BINARY_RESULT_OF(x -= y, result_of_minus_assign);
+    BOOST_BINARY_RESULT_OF(x *= y, result_of_multiplies_assign);
+    BOOST_BINARY_RESULT_OF(x /= y, result_of_divides_assign);
+    BOOST_BINARY_RESULT_OF(x %= y, result_of_modulus_assign);
+
+    BOOST_BINARY_RESULT_OF(x &= y, result_of_and_assign);
+    BOOST_BINARY_RESULT_OF(x |= y, result_of_or_assign);
+    BOOST_BINARY_RESULT_OF(x ^= y, result_of_xor_assign);
+    BOOST_BINARY_RESULT_OF(x <<= y, result_of_shift_left_assign);
+    BOOST_BINARY_RESULT_OF(x >>= y, result_of_shift_right_assign);
+
+    BOOST_BINARY_RESULT_OF(x + y, result_of_plus);
+    BOOST_BINARY_RESULT_OF(x - y, result_of_minus);
+    BOOST_BINARY_RESULT_OF(x * y, result_of_multiplies);
+    BOOST_BINARY_RESULT_OF(x / y, result_of_divides);
+    BOOST_BINARY_RESULT_OF(x % y, result_of_modulus);
+
+    BOOST_BINARY_RESULT_OF(x & y, result_of_and);
+    BOOST_BINARY_RESULT_OF(x | y, result_of_or);
+    BOOST_BINARY_RESULT_OF(x ^ y, result_of_xor);
+    BOOST_BINARY_RESULT_OF(x << y, result_of_shift_left);
+    BOOST_BINARY_RESULT_OF(x >> y, result_of_shift_right);
+
+    BOOST_BINARY_RESULT_OF(x == y, result_of_equal_to);
+    BOOST_BINARY_RESULT_OF(x != y, result_of_not_equal_to);
+    BOOST_BINARY_RESULT_OF(x < y, result_of_less);
+    BOOST_BINARY_RESULT_OF(x <= y, result_of_less_equal);
+    BOOST_BINARY_RESULT_OF(x > y, result_of_greater);
+    BOOST_BINARY_RESULT_OF(x >= y, result_of_greater_equal);
+
+    BOOST_BINARY_RESULT_OF(x && y, result_of_logical_and);
+    BOOST_BINARY_RESULT_OF(x || y, result_of_logical_or);
+    BOOST_BINARY_RESULT_OF(true ? x : y, result_of_if_else);
+}
+
+using namespace boost;
+using namespace std;
+
+struct X {};
+X operator+(X, int);
+
+struct Y {};
+Y* operator+(Y, int);
+
+struct Z {};
+Z const* operator+(Z const&, int);
+Z& operator+(Z&, int);
+bool operator==(Z, Z);
+bool operator==(Z, int);
+
+struct W {};
+Z operator+(W, int);
+bool operator==(W, Z);
+
+int
+main()
+{
+    //  ASSIGN
+    {
+        typedef result_of_assign<int, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int&>::value));
+    }
+
+    {
+        typedef result_of_assign<int*, int*>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int*&>::value));
+    }
+
+    //  PLUS
+    {
+        typedef result_of_plus<int, double>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, double>::value));
+    }
+    {
+        typedef result_of_plus<double, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, double>::value));
+    }
+    {
+        typedef result_of_plus<int, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+    {
+        typedef result_of_plus<float, short>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, float>::value));
+    }
+    {
+        typedef result_of_plus<char, short>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+    {
+        typedef result_of_plus<long, short>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, long>::value));
+    }
+    {
+        typedef result_of_plus<long, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, long>::value));
+    }
+    {
+        typedef result_of_plus<X, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X>::value));
+    }
+    {
+        typedef result_of_plus<Y, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, Y*>::value));
+    }
+    {
+        typedef result_of_plus<Z, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, Z&>::value));
+    }
+    {
+        typedef result_of_plus<Z const, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, Z const*>::value));
+    }
+    {
+        typedef result_of_plus<complex<double>, double>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, complex<double> >::value));
+    }
+    {
+        typedef result_of_plus<double, complex<double> >::type result;
+        BOOST_STATIC_ASSERT((is_same<result, complex<double> >::value));
+    }
+    {
+        typedef result_of_plus<int*, size_t>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int*>::value));
+    }
+
+    //  INDEX
+    {
+        typedef result_of_index<int(&)[3], int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int&>::value));
+    }
+    {
+        typedef result_of_index<X(&)[3], int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X&>::value));
+    }
+    {
+        typedef result_of_index<X const(&)[3], int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X const&>::value));
+    }
+    {
+        typedef result_of_index<X*, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X&>::value));
+    }
+    {
+        typedef result_of_index<X const*, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X const&>::value));
+    }
+    {
+        typedef result_of_index<vector<int>, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, vector<int>::reference>::value));
+    }
+    {
+        typedef result_of_index<vector<int> const, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+    {
+        typedef result_of_index<vector<X> const, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, vector<X>::const_reference>::value));
+    }
+    {
+        typedef result_of_index<vector<X>, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, vector<X>::reference>::value));
+    }
+    {
+        typedef result_of_index<string, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, string::reference>::value));
+    }
+    {
+        typedef result_of_index<vector<int>::iterator, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, vector<int>::iterator::reference>::value));
+    }
+    {
+        typedef result_of_index<vector<int>::const_iterator, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+    {
+        typedef result_of_index<vector<X>::const_iterator, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, vector<X>::const_iterator::reference>::value));
+    }
+    {
+        typedef result_of_index<map<char, X>, char>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, map<char, X>::mapped_type>::value));
+    }
+
+    //  PLUS ASSIGN
+    {
+        typedef result_of_plus_assign<int, char>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int&>::value));
+    }
+    {
+        typedef result_of_plus_assign<double, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, double&>::value));
+    }
+    {
+        typedef result_of_plus_assign<complex<double>, double>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, complex<double>&>::value));
+    }
+
+    //  SHIFT LEFT
+    {
+        typedef result_of_shift_left<int, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+    {
+        typedef result_of_shift_left<short, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+    {
+        typedef result_of_shift_left<ostream, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, ostream&>::value));
+    }
+
+    //  EQUAL
+    {
+        typedef result_of_equal_to<int, double>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, bool>::value));
+    }
+    {
+        typedef result_of_equal_to<double, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, bool>::value));
+    }
+    {
+        typedef result_of_equal_to<int, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, bool>::value));
+    }
+    {
+        typedef result_of_equal_to<float, short>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, bool>::value));
+    }
+    {
+        typedef result_of_equal_to<char, short>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, bool>::value));
+    }
+    {
+        typedef result_of_equal_to<Z, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, bool>::value));
+    }
+    {
+        typedef result_of_equal_to<Z, Z>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, bool>::value));
+    }
+    {
+        typedef result_of_equal_to<W, Z>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, bool>::value));
+    }
+
+    //  MINUS (pointers)
+    {
+        typedef result_of_minus<X*, X*>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, std::ptrdiff_t>::value));
+    }
+
+    //  DEREFERENCE
+    {
+        typedef result_of_dereference<X*>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X&>::value));
+    }
+    {
+        typedef result_of_dereference<vector<X>::iterator>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X&>::value));
+    }
+    {
+        typedef result_of_dereference<shared_ptr<X> >::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X&>::value));
+    }
+
+    //  ADDRESS OF
+    {
+        typedef result_of_reference<X>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X*>::value));
+    }
+    {
+        typedef result_of_reference<X const>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X const*>::value));
+    }
+
+    //  PRE INCREMENT
+    {
+        typedef result_of_pre_increment<int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int&>::value));
+    }
+
+    //  POST INCREMENT
+    {
+        typedef result_of_post_increment<int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+
+    //  IF-ELSE-EXPRESSION ( c ? a : b )
+    {
+        typedef result_of_if_else<int, char>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+    {
+        typedef result_of_if_else<int, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int&>::value));
+    }
+    {
+        typedef result_of_if_else<int const, int const>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int>::value));
+    }
+    {
+        typedef result_of_if_else<X, X>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X&>::value));
+    }
+    {
+        typedef result_of_if_else<X const&, X const&>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X const&>::value));
+    }
+
+    //  DEDUCTION FAILURE
+    {
+        typedef result_of_plus<W, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, error_cant_deduce_type>::value));
+    }
+    
+    // local_reference
+    {
+        using phoenix::detail::local_reference;
+        typedef result_of_assign<local_reference<int>, int>::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int&>::value));
+    }
+
+    // local_reference
+    {
+        using phoenix::detail::local_reference;
+        typedef result_of_pre_increment<local_reference<int> >::type result;
+        BOOST_STATIC_ASSERT((is_same<result, int&>::value));
+    }
+
+    // local_reference
+    {
+        using phoenix::detail::local_reference;
+        typedef result_of_if_else<local_reference<X const>, local_reference<X const> >::type result;
+        BOOST_STATIC_ASSERT((is_same<result, X const&>::value));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/function/function_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/function/function_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,116 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <cmath>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+    struct test_impl
+    {
+        typedef void result_type;
+        void operator()() const
+        {
+            cout << "Test lazy functions...\n";
+        }
+    };
+
+    function<test_impl> test;
+
+    struct sqr_impl
+    {
+        template <typename Arg>
+        struct result
+        {
+            typedef Arg type;
+        };
+
+        template <typename Arg>
+        Arg operator()(Arg n) const
+        {
+            return n * n;
+        }
+    };
+
+    function<sqr_impl> sqr;
+
+    struct fact_impl
+    {
+        template <typename Arg>
+        struct result
+        {
+            typedef Arg type;
+        };
+
+        template <typename Arg>
+        Arg operator()(Arg n) const
+        {
+            return (n <= 0) ? 1 : n * (*this)(n-1);
+        }
+    };
+
+    function<fact_impl> fact;
+
+    struct pow_impl
+    {
+        template <typename Arg1, typename Arg2>
+        struct result
+        {
+            typedef Arg1 type;
+        };
+
+        template <typename Arg1, typename Arg2>
+        Arg1 operator()(Arg1 a, Arg2 b) const
+        {
+            return pow(a, b);
+        }
+    };
+
+    function<pow_impl> power;
+
+    struct add_impl
+    {
+        template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+        struct result
+        {
+            typedef Arg1 type;
+        };
+
+        template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+        Arg1 operator()(Arg1 a, Arg2 b, Arg3 c, Arg4 d) const
+        {
+            return a + b + c + d;
+        }
+    };
+
+    function<add_impl> add;
+
+int
+main()
+{
+    int i5 = 5;
+    double d5 = 5, d3 = 3;
+
+    test()();
+    BOOST_TEST(sqr(arg1)(i5) == (i5*i5));
+    BOOST_TEST(fact(4)() == 24);
+    BOOST_TEST(fact(arg1)(i5) == 120);
+    BOOST_TEST((int)power(arg1, arg2)(d5, d3) == (int)pow(d5, d3));
+    BOOST_TEST((sqr(arg1) + 5)(i5) == ((i5*i5)+5));
+    BOOST_TEST(add(arg1, arg1, arg1, arg1)(i5) == (5+5+5+5));
+
+    int const ic5 = 5;
+    // testing consts
+    BOOST_TEST(sqr(arg1)(ic5) == (ic5*ic5));
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/object/cast_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/object/cast_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,63 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <string>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+struct T
+{
+    string foo() { return "T"; }
+};
+
+struct U : T
+{
+    string foo() { return "U"; }
+};
+
+struct VT
+{
+    virtual string foo() { return "T"; }
+};
+
+struct VU : VT
+{
+    virtual string foo() { return "U"; }
+};
+
+int
+main()
+{
+    {
+        U u;
+        BOOST_TEST(arg1(u).foo() == "U");
+        BOOST_TEST(static_cast_<T&>(arg1)(u).foo() == "T");
+    }
+
+    {
+        U const u = U();
+        BOOST_TEST(const_cast_<U&>(arg1)(u).foo() == "U");
+    }
+
+    {
+        VU u;
+        VT* tp = &u;
+        BOOST_TEST(arg1(tp)->foo() == "U");
+        BOOST_TEST(dynamic_cast_<VU*>(arg1)(tp) != 0);
+    }
+
+    {
+        void* p = 0;
+        reinterpret_cast_<VU*>(arg1)(p); // compile test only
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/object/new_delete_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/object/new_delete_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,52 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <boost/shared_ptr.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int n = 0;
+
+struct X
+{
+    X(int, int, int) { cout << "new X(int, int, int)" << endl; ++n; }
+    X() { cout << "new X" << endl; ++n; }
+    ~X() { cout << "delete X" << endl; --n; }
+};
+
+int
+main()
+{
+    {
+        vector<X*> v(10);
+
+        for_each(v.begin(), v.end(), arg1 = new_<X>());
+        for_each(v.begin(), v.end(), delete_(arg1));
+
+        for_each(v.begin(), v.end(), arg1 = new_<X>(1, 2, 3));
+        for_each(v.begin(), v.end(), delete_(arg1));
+    }
+
+    {
+        using boost::shared_ptr;
+        vector<shared_ptr<X> > v(10);
+        for_each(v.begin(), v.end(),
+            arg1 = construct<shared_ptr<X> >(new_<X>())
+        );
+    }
+
+    BOOST_TEST(n == 0);
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/arithmetic_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/arithmetic_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,54 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace std;
+
+int
+main()
+{
+    {
+        int x = 123;
+
+        BOOST_TEST((ref(x) += 456)() == 123 + 456);
+        BOOST_TEST(x == 123 + 456);
+        BOOST_TEST((ref(x) -= 456)() == 123);
+        BOOST_TEST(x == 123);
+        BOOST_TEST((ref(x) *= 456)() == 123 * 456);
+        BOOST_TEST(x == 123 * 456);
+        BOOST_TEST((ref(x) /= 456)() == 123);
+        BOOST_TEST(x == 123);
+
+        int& r1 = (ref(x) += 456)(); // should be an lvalue
+        int& r2 = (ref(x) -= 456)(); // should be an lvalue
+        int& r3 = (ref(x) *= 456)(); // should be an lvalue
+        int& r4 = (ref(x) /= 456)(); // should be an lvalue
+        BOOST_TEST(r1 == 123 && r2 == 123 && r3 == 123 && r4 == 123);
+
+        BOOST_TEST((ref(x) %= 456)() == 123 % 456);
+        BOOST_TEST(x == 123 % 456);
+    }
+
+    {
+        BOOST_TEST((val(123) + 456)() == 123 + 456);
+        BOOST_TEST((val(123) - 456)() == 123 - 456);
+        BOOST_TEST((val(123) * 456)() == 123 * 456);
+        BOOST_TEST((val(123) / 456)() == 123 / 456);
+        BOOST_TEST((val(123) % 456)() == 123 % 456);
+
+        BOOST_TEST((123 + val(456))() == 123 + 456);
+        BOOST_TEST((123 - val(456))() == 123 - 456);
+        BOOST_TEST((123 * val(456))() == 123 * 456);
+        BOOST_TEST((123 / val(456))() == 123 / 456);
+        BOOST_TEST((123 % val(456))() == 123 % 456);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/bitwise_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/bitwise_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,73 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    {
+        int x;
+        int y;
+
+        x = 123;
+        y = 123;
+        (ref(x) &= 456)();
+        y &= 456;
+        BOOST_TEST(x == y);
+
+        x = 123;
+        y = 123;
+        (ref(x) |= 456)();
+        y |= 456;
+        BOOST_TEST(x == y);
+
+        x = 123;
+        y = 123;
+        (ref(x) ^= 456)();
+        y ^= 456;
+        BOOST_TEST(x == y);
+
+        x = 123;
+        y = 123;
+        (ref(x) <<= 4)();
+        y <<= 4;
+        BOOST_TEST(x == y);
+
+        x = 1230000;
+        y = 1230000;
+        (ref(x) >>= 4)();
+        y >>= 4;
+        BOOST_TEST(x == y);
+
+        int& r1 = (ref(x) &= 456)(); // should be an lvalue
+        int& r2 = (ref(x) |= 456)(); // should be an lvalue
+        int& r3 = (ref(x) ^= 456)(); // should be an lvalue
+        int& r4 = (ref(x) <<= 4)(); // should be an lvalue
+        int& r5 = (ref(x) >>= 4)(); // should be an lvalue
+        BOOST_TEST(&r1 == &r2 && &r2 == &r3 && &r3 == &r4 && &r4 == &r5);
+    }
+
+    {
+        BOOST_TEST((val(123) & 456)() == (123 & 456));
+        BOOST_TEST((val(123) | 456)() == (123 | 456));
+        BOOST_TEST((val(123) ^ 456)() == (123 ^ 456));
+        BOOST_TEST((val(123) << 4)() == (123 << 4));
+        BOOST_TEST((val(1230000) >> 4)() == (1230000 >> 4));
+
+        char const* s = "Yabadabadoo!!!\n";
+        (cout << arg1)(s);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/comparison_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/comparison_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,28 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace std;
+
+int
+main()
+{
+    {
+        BOOST_TEST(!(val(123) == 456)());
+        BOOST_TEST((val(123) != 456)());
+        BOOST_TEST(!(val(123) > 456)());
+        BOOST_TEST((val(123) < 456)());
+        BOOST_TEST(!(val(123) > 456)());
+        BOOST_TEST((val(123) <= 123)());
+        BOOST_TEST((val(123) >= 123)());
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/if_else_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/if_else_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,34 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    {
+        int x = 0;
+        int y = 0;
+        bool c = false;
+
+        BOOST_TEST(if_else(arg1, 1234, 5678)(c) == 5678);
+        BOOST_TEST(if_else(arg1, 1234, 'x')(c) == 'x');
+
+        int& r = if_else(arg1, ref(x), ref(y))(c); // should be an lvalue
+        BOOST_TEST(&y == &r);
+
+        (if_else(arg1, ref(x), ref(y)) = 986754321)(c);
+        BOOST_TEST(y == 986754321);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/io_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/io_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,51 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <algorithm>
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int     i100 = 100;
+    string hello = "hello";
+    const char* world = " world";
+
+    int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+    vector<int> v(init, init+10);
+
+    char const* msg = "cout assert\n";
+    (cout << arg1)(msg);
+    (cout << arg1 << endl)(hello);
+    (arg1 << hex)(cout);
+    (cout << val(hello))();
+
+    (cout << val(hello) << world << ", you da man!\n")();
+    for_each(v.begin(), v.end(), cout << arg1 << ',');
+
+    (cout << arg1 << "this is it, shukz:" << hex << arg2 << endl << endl)(msg, i100);
+
+    int in;
+    int out = 12345;
+    stringstream sstr;
+    (sstr << arg1)(out);
+    (sstr >> arg1)(in);
+    BOOST_TEST(in == out);
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/logical_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/logical_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,36 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    {
+        bool x = false;
+        bool y = true;
+
+        BOOST_TEST((!arg1)(x) == true);
+        BOOST_TEST((!arg1)(y) == false);
+        BOOST_TEST((arg1 || arg2)(x, y) == true);
+        BOOST_TEST((arg1 && arg2)(x, y) == false);
+
+        // short circuiting:
+        int i = 1234;
+        (arg1 || (arg2 = 4567))(y, i);
+        BOOST_TEST(i == 1234);
+        (arg1 && (arg2 = 4567))(y, i);
+        BOOST_TEST(i == 4567);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/member.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/member.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,83 @@
+/*=============================================================================
+    Copyright (c) 2005-2007 Dan Marsden
+    Copyright (c) 2005-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)
+==============================================================================*/
+
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <memory>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
+
+namespace
+{
+    struct Test
+    {
+        int value;
+
+        int func(int n) const { return n; }
+        int dunc() { return 10; }
+    };
+}
+
+int main()
+{
+    using namespace boost::phoenix;
+    using namespace boost::phoenix::arg_names;
+    using namespace boost;
+
+    Test test = {1};
+    const Test* cptr = &test;
+    Test* ptr = &test;
+
+    BOOST_TEST((val(ptr)->*&Test::value)() == 1);
+    BOOST_TEST((val(cptr)->*&Test::value)() == 1);
+    BOOST_TEST((arg1->*&Test::value)(cptr) == 1);
+
+    ((val(ptr)->*&Test::value) = 2)();
+    BOOST_TEST(test.value == 2);
+
+    BOOST_TEST((val(ptr)->*&Test::func)(3)() == 3);
+    BOOST_TEST((val(cptr)->*&Test::func)(4)() == 4);
+    BOOST_TEST((val(ptr)->*&Test::dunc)()() == 10);
+
+    BOOST_TEST((arg1->*&Test::func)(5)(ptr) == 5);
+
+    shared_ptr<Test> sptr(new Test(test));
+
+    BOOST_TEST((arg1->*&Test::value)(sptr) == 2);
+    BOOST_TEST((arg1->*&Test::func)(6)(sptr) == 6);
+
+    scoped_ptr<Test> scptr(new Test(test));
+
+    BOOST_TEST((arg1->*&Test::value)(scptr) == 2);
+    BOOST_TEST((arg1->*&Test::func)(7)(scptr) == 7);
+
+    shared_ptr<const Test> csptr(new Test(test));
+
+    BOOST_TEST((arg1->*&Test::value)(csptr) == 2);
+    BOOST_TEST((arg1->*&Test::func)(8)(csptr) == 8);
+
+    scoped_ptr<const Test> cscptr(new Test(test));
+
+    BOOST_TEST((arg1->*&Test::value)(cscptr) == 2);
+    BOOST_TEST((arg1->*&Test::func)(9)(cscptr) == 9);
+
+    std::auto_ptr<Test> aptr(new Test(test));
+
+    BOOST_TEST((arg1->*&Test::value)(aptr) == 2);
+    BOOST_TEST((arg1->*&Test::func)(10)(aptr) == 10);
+
+    std::auto_ptr<const Test> captr(new Test(test));
+
+    BOOST_TEST((arg1->*&Test::value)(captr) == 2);
+    BOOST_TEST((arg1->*&Test::func)(11)(captr) == 11);
+
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/test/operator/misc_binary_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/misc_binary_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,97 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <string>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    {   // From Phoenix 1.1 binary tests
+
+        int i2 = 2, i3 = 3, i = 5;
+        const char* world = " world";
+
+        BOOST_TEST((ref(i) = ref(i))() == 5);
+        BOOST_TEST((ref(i) = 3)() == 3);
+        BOOST_TEST(i == 3);
+        i = 5;
+        int x, y, z;
+        (ref(x) = ref(y) = ref(z) = 10)();
+        BOOST_TEST(x == 10 && y == 10 && z == 10);
+        BOOST_TEST((val(world)[3])() == world[3]);
+
+        BOOST_TEST((ref(i) += 5)() == 10);
+        BOOST_TEST((ref(i) -= 5)() == 5);
+        BOOST_TEST((ref(i) *= 5)() == 25);
+        BOOST_TEST((ref(i) /= 5)() == 5);
+        BOOST_TEST((ref(i) %= 2)() == 1);
+
+        BOOST_TEST((ref(i) <<= 3)() == 8);
+        BOOST_TEST((ref(i) >>= 1)() == 4);
+        BOOST_TEST((ref(i) |= 0xFF)() == 0xFF);
+        BOOST_TEST((ref(i) &= 0xF0)() == 0xF0);
+        BOOST_TEST((ref(i) ^= 0xFFFFFFFF)() == int(0xFFFFFF0F));
+
+        BOOST_TEST((val(5) == val(5))());
+        BOOST_TEST((val(5) == 5)());
+
+        BOOST_TEST((arg1 + arg2)(i2, i3) == i2 + i3);
+        BOOST_TEST((arg1 - arg2)(i2, i3) == i2 - i3);
+        BOOST_TEST((arg1 * arg2)(i2, i3) == i2 * i3);
+        BOOST_TEST((arg1 / arg2)(i2, i3) == i2 / i3);
+        BOOST_TEST((arg1 % arg2)(i2, i3) == i2 % i3);
+        BOOST_TEST((arg1 & arg2)(i2, i3) == (i2 & i3));
+        BOOST_TEST((arg1 | arg2)(i2, i3) == (i2 | i3));
+        BOOST_TEST((arg1 ^ arg2)(i2, i3) == (i2 ^ i3));
+        BOOST_TEST((arg1 << arg2)(i2, i3) == i2 << i3);
+        BOOST_TEST((arg1 >> arg2)(i2, i3) == i2 >> i3);
+
+        BOOST_TEST((val(5) != val(6))());
+        BOOST_TEST((val(5) < val(6))());
+        BOOST_TEST(!(val(5) > val(6))());
+        BOOST_TEST((val(5) < val(6))());
+        BOOST_TEST((val(5) <= val(6))());
+        BOOST_TEST((val(5) <= val(5))());
+        BOOST_TEST((val(7) >= val(6))());
+        BOOST_TEST((val(7) >= val(7))());
+
+        BOOST_TEST((val(false) && val(false))() == false);
+        BOOST_TEST((val(true) && val(false))() == false);
+        BOOST_TEST((val(false) && val(true))() == false);
+        BOOST_TEST((val(true) && val(true))() == true);
+
+        BOOST_TEST((val(false) || val(false))() == false);
+        BOOST_TEST((val(true) || val(false))() == true);
+        BOOST_TEST((val(false) || val(true))() == true);
+        BOOST_TEST((val(true) || val(true))() == true);
+    }
+
+    {  // From Phoenix 1.1 mixed_binary tests
+
+        int     i1 = 1, i2 = 2, i50 = 50, i100 = 100;
+        double  d2_5 = 2.5;
+        string hello = "hello";
+        const char* world = " world";
+
+        BOOST_TEST((arg1 + arg2)(i100, i50) == (i100 + i50));
+        BOOST_TEST((arg1 + 3)(i100) == (3 + i100));
+        BOOST_TEST((arg1 + arg2)(hello, world) == "hello world");
+        BOOST_TEST((arg1 + arg2)(i1, d2_5) == (i1 + d2_5));
+
+        BOOST_TEST((*(arg1 + arg2))(world, i2) == *(world + i2));
+        BOOST_TEST((*(arg1 + arg2))(i2, world) == *(i2 + world));
+        BOOST_TEST((*(val(world+i2) - arg1))(i2) == *world);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/self_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/self_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,55 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <vector>
+#include <string>
+#include <map>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    {
+        int x = 123;
+        BOOST_TEST((&arg1)(x) == &x);
+        BOOST_TEST((*&arg1)(x) == 123);
+
+        int y = 968;
+        (ref(x) = arg1)(y);
+        BOOST_TEST(x == y);
+
+        (arg1 = 456)(x);
+        BOOST_TEST(x == 456);
+        int& r = (arg1 = 456)(x); // must be an lvalue
+        BOOST_TEST(&r == &x);
+
+        int c[] = { 1, 2, 3, 4, 5 };
+        BOOST_TEST((arg1[3])(c) == 4);
+
+        int& r2 = (arg1[3])(c); // must be an lvalue
+        BOOST_TEST(&r2 == &c[3]);
+
+        vector<string> v;
+        v.push_back("a");
+        v.push_back("b");
+        v.push_back("c");
+        v.push_back("d");
+
+        BOOST_TEST((arg1[3])(v) == "d");
+
+        map<string, int> m;
+        (arg1["Kimpo"] = arg2)(m, x);
+        BOOST_TEST(m["Kimpo"] == x);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/operator/unary_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/operator/unary_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,64 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    {
+        BOOST_TEST((-val(123))() == -123);
+        BOOST_TEST((- -val(123))() == 123);
+        BOOST_TEST((+val(123))() == 123);
+    }
+
+    {
+        int x = 123;
+
+        BOOST_TEST((++ref(x))() == 124);
+        BOOST_TEST(x == 124);
+        BOOST_TEST((--ref(x))() == 123);
+        BOOST_TEST(x == 123);
+
+        BOOST_TEST((ref(x)++)() == 123);
+        BOOST_TEST(x == 124);
+        BOOST_TEST((ref(x)--)() == 124);
+        BOOST_TEST(x == 123);
+
+        int& r1 = (++ref(x))(); // should be an lvalue
+        int& r2 = (--ref(x))(); // should be an lvalue
+        BOOST_TEST(r1 == 123 && r2 == 123);
+    }
+
+    {   // From Phoenix 1.1 unary tests
+
+        int i1 = 1, i = 5;
+
+        BOOST_TEST((!val(true))() == false);
+        BOOST_TEST((-val(1))() == -1);
+        BOOST_TEST((+val(1))() == +1);
+        BOOST_TEST((~val(1))() == ~1);
+        BOOST_TEST(*(&arg1)(i1) == *(&i1));
+        BOOST_TEST((&arg1)(i1) == &i1);
+
+        BOOST_TEST((*val(&i1))() == *(&i1));
+        BOOST_TEST((*&arg1)(i1) == *(&i1));
+        BOOST_TEST((++ref(i))() == 6);
+        BOOST_TEST((--ref(i))() == 5);
+        BOOST_TEST((ref(i)++)() == 5);
+        BOOST_TEST(i == 6);
+        BOOST_TEST((ref(i)--)() == 6);
+        BOOST_TEST(i == 5);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/scope/bug_000008.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/scope/bug_000008.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,96 @@
+/*=============================================================================
+    Copyright (c) 2003 Martin Wille
+    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)
+=============================================================================*/
+
+  // see http://article.gmane.org/gmane.comp.parsers.spirit.general/4575
+  // or https://sf.net/mailarchive/forum.php?thread_id=2692308&forum_id=1595
+  // for a description of the bug being tested for by this program
+  //
+  // This code is borrowed from Spirit's bug_000008.cpp test for multithreads.
+#include <iostream>
+#include <boost/config.hpp>
+#include <boost/assert.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+#if defined(DONT_HAVE_BOOST)                        \
+    || !defined(BOOST_HAS_THREADS)                  \
+    || defined(BOOST_DISABLE_THREADS)               \
+    || (defined(__GNUC__) && defined(__WIN32__))    // MinGW
+#define SKIP_TEST
+#endif
+
+
+#if defined(SKIP_TEST)
+// we end here if we can't do multithreading
+static void skipped()
+{
+    std::cout << "skipped\n";
+}
+
+int
+main()
+{
+    skipped();
+    return boost::report_errors();
+}
+
+#else
+// the real MT stuff
+
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_scope.hpp>
+#include <boost/thread.hpp>
+
+static const int number_of_calls_per_thread=20000;
+
+struct test_dynamic : boost::phoenix::dynamic<int>
+{
+    test_dynamic() : b(*this) {}
+    member1 b;
+};
+
+void
+in_thread(void)
+{
+    test_dynamic s; // should now be a local
+
+    for (int i = 0; i < number_of_calls_per_thread; ++i)
+    {
+        boost::phoenix::dynamic_frame<test_dynamic::self_type> frame(s);
+        (s.b = 123)();
+        {
+            boost::phoenix::dynamic_frame<test_dynamic::self_type> frame(s);
+            (s.b = 456)();
+            BOOST_ASSERT((s.b == 456)());
+        }
+        BOOST_ASSERT((s.b == 123)());
+    }
+}
+
+void
+bug_000008()
+{
+    boost::thread t1(in_thread);
+    boost::thread t2(in_thread);
+    boost::thread t3(in_thread);
+    boost::thread t4(in_thread);
+
+    t1.join();
+    t2.join();
+    t3.join();
+    t4.join();
+}
+
+int
+main()
+{
+    bug_000008();
+    return boost::report_errors();
+}
+
+#endif
+
Added: trunk/libs/spirit/phoenix/test/scope/dynamic_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/scope/dynamic_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,79 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <string>
+
+#define PHOENIX_LIMIT 6
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_scope.hpp>
+
+struct my_dynamic : ::boost::phoenix::dynamic<int, std::string, double>
+{
+    my_dynamic() : num(*this), message(*this), real(*this) {}
+
+    member1 num;
+    member2 message;
+    member3 real;
+};
+
+//  You may also use the macro below to achieve the same as above:
+//
+//  PHOENIX_DYNAMIC(
+//      my_dynamic,
+//          (int, num)
+//          (std::string, message)
+//          (double, real)
+//  );
+
+int
+main()
+{
+    using namespace boost::phoenix;
+    using namespace boost::phoenix::arg_names;
+
+    my_dynamic clos;
+
+    {   //  First stack frame
+        dynamic_frame<my_dynamic::self_type> frame(clos);
+        (clos.num = 123)();
+        (clos.num += 456)();
+        (clos.real = clos.num / 56.5)();
+        (clos.message = "Hello " + std::string("World "))();
+
+        {   //  Second stack frame
+            dynamic_frame<my_dynamic::self_type> frame(clos);
+            (clos.num = 987)();
+            (clos.message = "Abracadabra ")();
+            (clos.real = clos.num * 1e30)();
+
+            {   //  Third stack frame
+                boost::fusion::vector<int, char const*, double> init(-1, "Direct Init ", 3.14);
+                dynamic_frame<my_dynamic::self_type> frame(clos, init);
+
+                (std::cout << clos.message << clos.num << ", " << clos.real << '\n')();
+                BOOST_TEST(clos.num() == -1);
+                BOOST_TEST(clos.real() == 3.14);
+                BOOST_TEST(clos.message() == "Direct Init ");
+            }
+
+            (std::cout << clos.message << clos.num << ", " << clos.real << '\n')();
+            BOOST_TEST(clos.num() == 987);
+            BOOST_TEST(clos.real() == clos.num() * 1e30);
+            BOOST_TEST(clos.message() == "Abracadabra ");        
+        }
+
+        (std::cout << clos.message << clos.num << ", " << clos.real << '\n')();
+        BOOST_TEST(clos.num() == 123+456);
+        BOOST_TEST(clos.real() == clos.num() / 56.5);
+        BOOST_TEST(clos.message() == "Hello " + std::string("World "));
+    }
+
+    return 0;
+}
Added: trunk/libs/spirit/phoenix/test/scope/lambda_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/scope/lambda_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,179 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <cmath>
+#include <algorithm>
+#include <vector>
+
+#define PHOENIX_LIMIT 5
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_scope.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace boost { namespace phoenix
+{
+    struct for_each_impl
+    {
+        template <typename C, typename F>
+        struct result
+        {
+            typedef void type;
+        };
+
+        template <typename C, typename F>
+        void operator()(C& c, F f) const
+        {
+            std::for_each(c.begin(), c.end(), f);
+        }
+    };
+
+    function<for_each_impl> const for_each = for_each_impl();
+
+    struct push_back_impl
+    {
+        template <typename C, typename T>
+        struct result
+        {
+            typedef void type;
+        };
+
+        template <typename C, typename T>
+        void operator()(C& c, T& x) const
+        {
+            c.push_back(x);
+        }
+    };
+
+    function<push_back_impl> const push_back = push_back_impl();
+}}
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace boost::phoenix::local_names;
+using namespace std;
+
+struct zzz {};
+
+int
+main()
+{
+    {
+        int x = 1;
+        int y = lambda[_1]()(x);
+        BOOST_TEST(x == y);
+    }
+    
+    {
+        int x = 1, y = 10;
+        BOOST_TEST(
+            (_1 + lambda[_1 + 2])(x)(y) == 1+10+2
+        );
+        BOOST_TEST(
+            (_1 + lambda[-_1])(x)(y) == 1+-10
+        );
+    }
+    
+    {
+        int x = 1, y = 10, z = 13;
+        BOOST_TEST(
+            lambda(_a = _1, _b = _2)
+            [
+                _1 + _a + _b
+            ]
+            (x, z)(y) == x + y + z
+        );
+    }
+
+    {
+        int x = 4;
+        int y = 5;
+        lambda(_a = _1)[_a = 555](x)();
+        BOOST_TEST(x == 555);
+        (void)y;
+    }
+
+    {
+        int x = 1;
+        long x2 = 2;
+        short x3 = 3;
+        char const* y = "hello";
+        zzz z;
+
+        BOOST_TEST(lambda[_1](x)(y) == y);
+        BOOST_TEST(lambda(_a = _1)[_a](x)(y) == x);        
+        BOOST_TEST(lambda(_a = _1)[lambda[_a]](x)(y)(z) == x);
+        BOOST_TEST(lambda(_a = _1)[lambda[_a + _1]](x)(y)(x) == 2);
+        BOOST_TEST(lambda(_a = _1)[lambda(_b = _1)[_a + _b + _1]](x)(x2)(x3) == 6);
+    }
+    
+    {
+        int x = 1, y = 10;
+        BOOST_TEST(
+            (_1 + lambda(_a = _1)[_a + _1 + 2])(x)(y) == 1+1+10+2
+        );
+    }
+
+    {
+        int x = 1, y = 10;
+        BOOST_TEST(
+            (_1 +
+                lambda(_a = _1)
+                [
+                    _a + lambda[_a + 2]
+                ]
+            )
+            (x)(y)(y) == 1+1+1+2
+        );
+    }
+    
+    {
+        using boost::phoenix::for_each;
+
+        int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+        std::vector<int> v(init, init+10);
+
+        int x = 0;
+        for_each(_1, lambda(_a = _2)[_a += _1])(v, x);
+        BOOST_TEST(x == 55);
+    }
+
+    {
+        using boost::phoenix::for_each;
+        using boost::phoenix::push_back;
+
+        int x = 10;
+        std::vector<std::vector<int> > v(10);
+
+        for_each(_1, lambda(_a = _2)[push_back(_1, _a)])(v, x);
+
+        int y = 0;
+        for_each(arg1, lambda[ref(y) += _1[0]])(v);
+        BOOST_TEST(y == 100);
+    }
+
+    {
+        int x = 1, y = 10, z = 13;
+        BOOST_TEST(
+            lambda(_a = _1, _b = _2)
+            [
+                _1 + _a + _b
+            ]
+            (x, z)(y) == x + y + z
+        );
+    }
+
+    {
+        int x = (let(_a = lambda[val(1)])[_a])()();
+        BOOST_TEST(x == 1);
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/phoenix/test/scope/let_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/scope/let_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,146 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <cmath>
+#include <algorithm>
+#include <vector>
+
+#define PHOENIX_LIMIT 6
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_scope.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace boost::phoenix::local_names;
+using namespace std;
+
+int
+main()
+{
+    {
+        int x = 1;
+        BOOST_TEST(
+            let(_a = _1)
+            [
+                _a
+            ]
+            (x) == x
+        );
+    }
+    
+    {
+        int x = 1, y = 10;
+        BOOST_TEST(
+            let(_a = _1, _b = _2)
+            [
+                _a + _b
+            ]
+            (x, y) == x + y
+        );
+    }
+
+    {
+        int x = 1, y = 10, z = 13;
+        BOOST_TEST(
+            let(_x = _1, _y = _2)
+            [
+                let(_z = _3)
+                [
+                    _x + _y + _z
+                ]
+            ]
+            (x, y, z) == x + y + z
+        );
+    }
+
+    {
+        int x = 1, y = 10;
+        BOOST_TEST(
+            let(_x = _1) 
+            [
+                _x +
+                    let(_x = _2) 
+                    [
+                        -_x
+                    ]
+            ]
+            (x, y) == x + -y
+        );
+    }
+    
+    {
+        int x = 999;
+        BOOST_TEST(
+            let(_x = _1) // _x is a reference to _x
+            [
+                _x += 888
+            ]
+            (x) == 999 + 888
+        );
+        
+        BOOST_TEST(x == 888 + 999);    
+    }
+
+    {
+        int x = 999;
+        BOOST_TEST(
+            let(_x = val(_1)) // _x holds x by value 
+            [
+                val(_x += 888)
+            ]
+            (x) == x + 888
+        );
+        
+        BOOST_TEST(x == 999);    
+    }
+    
+    {
+        BOOST_TEST(
+            let(_a = 1, _b = 2, _c = 3, _d = 4, _e = 5)
+            [
+                _a + _b + _c + _d + _e
+            ]
+            () == 1 + 2 + 3 + 4 + 5
+        );
+    }
+    
+#ifdef PHOENIX_SHOULD_NOT_COMPILE_TEST
+    {
+        // disallow this:
+        int i;
+        (_a + _b)(i);
+    }
+#endif
+    
+    {
+        // show that we can return a local from an outer scope
+        int y = 0;
+        int x = (let(_a = 1)[let(_b = _1)[ _a ]])(y);
+        BOOST_TEST(x == 1);
+    }
+
+    {
+        // show that this code returns an lvalue
+        int i = 1;
+        let(_a = arg1)[ _a ](i)++;
+        BOOST_TEST(i == 2);
+    }
+
+    {
+        // show that what you put in is what you get out
+        int i = 1;
+        int& j = let(_a = arg1)[ _a ](i);
+        BOOST_TEST(&i == &j);
+    }
+    
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/phoenix/test/statement/exceptions.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/statement/exceptions.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,100 @@
+/*=============================================================================
+    Copyright (c) 2005-2007 Dan Marsden
+    Copyright (c) 2005-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)
+==============================================================================*/
+
+#include <stdexcept>
+#include <string>
+
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include <boost/detail/lightweight_test.hpp>
+
+int main()
+{
+    using namespace boost::phoenix;
+    using namespace boost::phoenix::arg_names;
+    using namespace std;
+
+    {
+        try
+        {
+            throw_(runtime_error("error"))();
+            BOOST_ERROR("exception should have been thrown");
+        }
+        catch(runtime_error& err)
+        {
+            BOOST_TEST(err.what() == string("error"));
+        }
+    }
+
+    {
+        try
+        {
+            try
+            {
+                throw runtime_error("error");
+            }
+            catch(exception&)
+            {
+                throw_()();
+                BOOST_ERROR("exception should have been rethrown");
+            }
+        }
+        catch(exception& err)
+        {
+            BOOST_TEST(err.what() == string("error"));
+        }
+    }
+
+    {
+        bool caught_exception = false;
+
+        try_
+        [ throw_(runtime_error("error")) ]
+        .catch_<exception>()
+        [ ref(caught_exception) = true ]();
+
+        BOOST_TEST(caught_exception);
+    }
+
+    {
+        bool caught_exception = false;
+        try_
+        [ throw_(runtime_error("error")) ]
+        .catch_all
+        [ ref(caught_exception) = true ]();
+        BOOST_TEST(caught_exception);
+    }
+
+    {
+        bool caught_correct_exception = false;
+        try_
+            [ throw_(runtime_error("error")) ]
+        .catch_<string>()
+            [ ref(caught_correct_exception) = false ]
+        .catch_<exception>()
+            [ ref(caught_correct_exception) = true]();
+
+        BOOST_TEST(caught_correct_exception);
+    }
+
+    {
+        bool caught_correct_exception = false;
+        try_
+            [ throw_(runtime_error("error")) ]
+        .catch_<string>()
+            [ ref(caught_correct_exception) = false ]
+        .catch_all
+            [ ref(caught_correct_exception) = true]();
+
+        BOOST_TEST(caught_correct_exception);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/statement/if_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/statement/if_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,70 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+    vector<int> v(init, init+10);
+
+    cout << dec;
+    int x = 0;
+
+    for_each(v.begin(), v.end(),
+        if_(arg1 > 3 && arg1 <= 8)
+        [
+            cout << arg1 << ", ",
+            ref(x) += arg1
+        ]
+    );
+
+    cout << endl;
+    BOOST_TEST(x == 4+5+6+7+8);
+
+    x = 0;
+    int y = 0;
+    int z = 0;
+
+    for_each(v.begin(), v.end(),
+        if_(arg1 > 5)
+        [
+            cout << arg1 << " > 5\n",
+            ref(x) += arg1
+        ]
+        .else_
+        [
+            if_(arg1 == 5)
+            [
+                cout << arg1 << " == 5\n",
+                ref(z) += arg1
+            ]
+            .else_
+            [
+                cout << arg1 << " < 5\n",
+                ref(y) += arg1
+            ]
+        ]
+    );
+
+    cout << endl;
+    BOOST_TEST(x == 6+7+8+9+10);
+    BOOST_TEST(y == 1+2+3+4);
+    BOOST_TEST(z == 5);
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/statement/loops_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/statement/loops_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,79 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+    vector<int> v(init, init+10);
+    vector<int> t = v;
+    cout << endl;
+    int x = 0;
+
+    for_each(v.begin(), v.end(),
+        (
+            while_(arg1--)
+            [
+                cout << arg1 << ", ",
+                ++ref(x)
+            ],
+            cout << val("\n")
+        )
+    );
+
+    BOOST_TEST(x == 1+2+3+4+5+6+7+8+9+10);
+    cout << endl;
+    v = t;
+    x = 0;
+
+    for_each(v.begin(), v.end(),
+        (
+            do_
+            [
+                cout << arg1 << ", ",
+                ++ref(x)
+            ]
+            .while_(arg1--),
+            cout << val("\n")
+        )
+    );
+
+    BOOST_TEST(x == 2+3+4+5+6+7+8+9+10+11);
+    cout << endl;
+    v = t;
+    x = 0;
+
+    int iii;
+    for_each(v.begin(), v.end(),
+        (
+            for_(ref(iii) = 0, ref(iii) < arg1, ++ref(iii))
+            [
+                cout << arg1 << ", ",
+                ++ref(x)
+            ],
+            cout << val("\n")
+        )
+    );
+
+    BOOST_TEST(x == 1+2+3+4+5+6+7+8+9+10);
+    cout << endl;
+    v = t;
+    x = 0;
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/phoenix/test/statement/switch_tests.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/phoenix/test/statement/switch_tests.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,69 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <vector>
+#include <algorithm>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+using namespace boost::phoenix;
+using namespace boost::phoenix::arg_names;
+using namespace std;
+
+int
+main()
+{
+    int init[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+    vector<int> v(init, init+10);
+
+    for_each(v.begin(), v.end(),
+        switch_(_1)
+        [
+            // wierd case, why not just use if(...), but valid, nonetheless
+            case_<4>(cout << val("<4>") << endl)
+        ]
+    );
+
+    cout << endl;
+
+    for_each(v.begin(), v.end(),
+        switch_(_1)
+        [
+            // wierd case, but valid, nonetheless
+            default_(cout << val("<any...>") << endl)
+        ]
+    );
+
+    cout << endl;
+
+    for_each(v.begin(), v.end(),
+        switch_(_1)
+        [
+            case_<1>(cout << val("<1>") << endl),
+            case_<2>(cout << val("<2>") << endl),
+            case_<3>(cout << val("<3>") << endl),
+            case_<4>(cout << val("<4>") << endl)
+        ]
+    );
+
+    cout << endl;
+
+    for_each(v.begin(), v.end(),
+        switch_(_1)
+        [
+            case_<1>(cout << val("<1>") << endl),
+            case_<2>(cout << val("<2>") << endl),
+            case_<3>(cout << val("<3>") << endl),
+            case_<4>(cout << val("<4>") << endl),
+            default_(cout << val("<over 4>") << endl)
+        ]
+    );
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/Jamfile
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/Jamfile	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,98 @@
+#==============================================================================
+#   Copyright (c) 2001-2007 Joel de Guzman
+#   Copyright (c) 2001-2008 Hartmut Kaiser
+#
+#   Use, modification and distribution is subject to the Boost Software
+#   License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+#   http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+
+# bring in rules for testing
+import testing ;
+
+{
+    test-suite spirit_v2 :
+
+    # run Qi tests
+    [ run qi/char.cpp                       : : : : ]
+    [ run qi/char_class.cpp                 : : : : ]
+    [ run qi/lit.cpp                        : : : : ]
+    [ run qi/int.cpp                        : : : : ]
+    [ run qi/uint.cpp                       : : : : ]
+    [ run qi/real.cpp                       : : : : ]
+    [ run qi/eps.cpp                        : : : : ]
+    [ run qi/none.cpp                       : : : : ]
+    [ run qi/lazy.cpp                       : : : : ]
+    [ run qi/tst.cpp                        : : : : ]
+    [ run qi/symbols.cpp                    : : : : ]
+    [ run qi/range_run.cpp                  : : : : ]
+    [ run qi/no_case.cpp                    : : : : ]
+    [ run qi/lexeme.cpp                     : : : : ]
+    [ run qi/raw.cpp                        : : : : ]
+    [ run qi/sequence.cpp                   : : : : ]
+    [ run qi/alternative.cpp                : : : : ]
+    [ run qi/sequential_or.cpp              : : : : ]
+    [ run qi/permutation.cpp                : : : : ]
+    [ run qi/difference.cpp                 : : : : ]
+    [ run qi/list.cpp                       : : : : ]
+    [ run qi/optional.cpp                   : : : : ]
+    [ run qi/kleene.cpp                     : : : : ]
+    [ run qi/plus.cpp                       : : : : ]
+    [ run qi/and_predicate.cpp              : : : : ]
+    [ run qi/not_predicate.cpp              : : : : ]
+    [ run qi/expect.cpp                     : : : : ]
+    [ run qi/rule.cpp                       : : : : ]
+    [ run qi/grammar.cpp                    : : : : ]
+    [ run qi/functor.cpp                    : : : : ]
+    [ run qi/match_manip.cpp                : : : : ]
+    [ run qi/binary.cpp                     : : : : ]
+    [ run qi/debug.cpp                      : : : : ]
+
+    [ compile-fail qi/grammar_fail.cpp      : : ]
+    [ compile-fail qi/rule_fail.cpp         : : ]
+
+    # run Karma tests
+    [ run karma/alternative.cpp             : : : : karma_alternative ]
+    [ run karma/binary.cpp                  : : : : karma_binary ]
+    [ run karma/case_handling.cpp           : : : : ]
+    [ run karma/center_alignment.cpp        : : : : ]
+    [ run karma/char.cpp                    : : : : karma_char ]
+    [ run karma/delimiter.cpp               : : : : ]
+    [ run karma/eps.cpp                     : : : : karma_eps ]
+    [ run karma/format_manip.cpp            : : : : ]
+    [ run karma/functor.cpp                 : : : : karma_functor ]
+    [ run karma/grammar.cpp                 : : : : karma_grammar ]
+    [ run karma/int_numerics.cpp            : : : : ]
+    [ run karma/kleene.cpp                  : : : : karma_kleene ]
+    [ run karma/lazy.cpp                    : : : : karma_lazy ]
+    [ run karma/left_alignment.cpp          : : : : ]
+    [ run karma/list.cpp                    : : : : karma_list ]
+    [ run karma/lit.cpp                     : : : : karma_lit ]
+    [ run karma/none.cpp                    : : : : karma_none ]
+    [ run karma/optional.cpp                : : : : karma_optional ]
+    [ run karma/pattern.cpp                 : : : : ]
+    [ run karma/real_numerics.cpp           : : : : ]
+    [ run karma/right_alignment.cpp         : : : : ]
+    [ run karma/sequence.cpp                : : : : karma_sequence ]
+
+    [ compile-fail karma/grammar_fail.cpp   : : karma_grammar_fail ]
+    [ compile-fail karma/rule_fail.cpp      : : karma_rule_fail ]
+
+    # run support tests
+    [ run support/hold_any.cpp              : : : : ]
+    [ run support/multi_pass_compile.cpp    : : : : ]
+    [ run support/multi_pass.cpp            : : : : ]
+
+    # run lexer tests
+    [ run lex/lexertl1.cpp                  : : : : ]
+    [ run lex/lexertl2.cpp                  : : : : ]
+    [ run lex/lexertl3.cpp                  : : : : ]
+    [ run lex/lexertl4.cpp                  : : : : ]
+    [ run lex/lexertl5.cpp                  : : : : ]
+    [ run lex/state_switcher_test.cpp       : : : : ]
+
+    ;
+
+}
+
+
Added: trunk/libs/spirit/test/karma/alternative.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/alternative.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,88 @@
+//  Copyright (c) 2001-2008 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)
+
+// #define KARMA_TEST_COMPILE_FAIL
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost;
+    using namespace boost::spirit;
+    
+    {
+        {
+            BOOST_TEST(test("x", char_('x') | char_('i')));
+            BOOST_TEST(test("xi", char_('x') << char_('i') | char_('i')));
+
+            variant<int, char> v (10);
+            BOOST_TEST(test("10", char_ | int_, v));
+            BOOST_TEST(test("a", char_('a') | char_ | int_, v));
+
+            v = 'c';
+            BOOST_TEST(test("c", char_ | int_, v));
+            BOOST_TEST(test("a", char_('a') | char_ | int_, v));
+        }
+
+        {
+            // test if alternatives with all components having unused 
+            // parameter return attributes them self
+            fusion::vector<char, char> v('a', 'b');
+            BOOST_TEST(test("axb", char_ << (char_('x') | char_('i')) << char_, v));
+            BOOST_TEST(test("axib", 
+                char_ << (char_('x') << char_('i') | char_('i')) << char_, v));
+        }
+
+        {
+            BOOST_TEST(test_delimited("x ", char_('x') | char_('i'), char_(' ')));
+            BOOST_TEST(test_delimited("x i ", 
+                char_('x') << char_('i') | char_('i'), char_(' ')));
+
+            variant<int, char> v (10);
+            BOOST_TEST(test_delimited("10 ", char_ | int_, v, char_(' ')));
+
+            v = 'c';
+            BOOST_TEST(test_delimited("c ", char_ | int_, v, char_(' ')));
+        }
+
+        {
+            // if nothing matches, the first explicit alternative will be chosen
+            variant<double, char const*> v (10.0);
+            BOOST_TEST(test("11", char_ | int_(11), v));
+            BOOST_TEST(test("10.0", double_ | int_(11), v));
+            BOOST_TEST(!test("", char_ | int_, v));
+
+            v = "c";
+            BOOST_TEST(test("11", char_ | int_(11), v));
+            BOOST_TEST(test("11", double_ | int_(11), v));
+            BOOST_TEST(!test("", char_ | int_, v));
+        }
+
+        {
+            // if nothing matches, the first explicit alternative will be chosen
+            variant<double, char const*> v (10.0);
+            BOOST_TEST(test_delimited("11 ", char_ | int_(11), v, char_(' ')));
+
+            v = "c";
+            BOOST_TEST(test_delimited("11 ", char_ | int_(11), v, char_(' ')));
+        }
+    }
+    
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/karma/binary.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/binary.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,101 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/karma_binary.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::phoenix;
+    using namespace boost::spirit::arg_names;
+
+    {   // test native endian binaries
+#ifdef BOOST_LITTLE_ENDIAN
+        BOOST_TEST(binary_test("\x01", 1, byte, 0x01));
+        BOOST_TEST(binary_test("\x01\x02", 2, word, 0x0201));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword, 0x04030201));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword,
+            0x0807060504030201LL));
+#endif
+#else
+        BOOST_TEST(binary_test("\x01", 1, byte, 0x01));
+        BOOST_TEST(binary_test("\x01\x02", 2, word, 0x0102));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword, 0x01020304));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword,
+            0x0102030405060708LL));
+#endif
+#endif
+    }
+
+    {   // test native endian binaries
+#ifdef BOOST_LITTLE_ENDIAN
+        BOOST_TEST(binary_test("\x01", 1, byte(0x01)));
+        BOOST_TEST(binary_test("\x01\x02", 2, word(0x0201)));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword(0x04030201)));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8,
+            qword(0x0807060504030201LL)));
+#endif
+#else
+        BOOST_TEST(binary_test("\x01", 1, byte(0x01)));
+        BOOST_TEST(binary_test("\x01\x02", 2, word(0x0102)));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, dword(0x01020304)));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8,
+            qword(0x0102030405060708LL)));
+#endif
+#endif
+    }
+
+    {   // test big endian binaries
+        BOOST_TEST(binary_test("\x01\x02", 2, big_word, 0x0102));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, big_dword, 0x01020304));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, big_qword,
+            0x0102030405060708LL));
+#endif
+    }
+
+    {
+        BOOST_TEST(binary_test("\x01\x02", 2, big_word(0x0102)));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, big_dword(0x01020304)));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8,
+            big_qword(0x0102030405060708LL)));
+#endif
+    }
+
+    {   // test little endian binaries
+        BOOST_TEST(binary_test("\x01\x02", 2, little_word, 0x0201));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, little_dword, 0x04030201));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8, little_qword,
+            0x0807060504030201LL));
+#endif
+    }
+
+    {
+        BOOST_TEST(binary_test("\x01\x02", 2, little_word(0x0201)));
+        BOOST_TEST(binary_test("\x01\x02\x03\x04", 4, little_dword(0x04030201)));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(binary_test("\x01\x02\x03\x04\x05\x06\x07\x08", 8,
+            little_qword(0x0807060504030201LL)));
+#endif
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/case_handling.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/case_handling.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,176 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+
+    {
+        using namespace boost::spirit::ascii;
+        
+        BOOST_TEST(test("x", lower['X']));
+        BOOST_TEST(test("x", lower['x']));
+        BOOST_TEST(test(L"x", lower[L'X']));
+        BOOST_TEST(test(L"x", lower[L'x']));
+
+        BOOST_TEST(test("x", lower[char_], 'X'));
+        BOOST_TEST(test("x", lower[char_], 'x'));
+        BOOST_TEST(test("x", lower[char_('X')]));
+        BOOST_TEST(test("x", lower[char_('x')]));
+
+        BOOST_TEST(test(" ", lower[space]));
+        BOOST_TEST(test("\t", lower[space], '\t'));
+        BOOST_TEST(test("\t", lower[space('\t')]));
+        
+        BOOST_TEST(test("x", lower[lower['X']]));
+        BOOST_TEST(test("x", lower[lower['x']]));
+        BOOST_TEST(test(L"x", lower[lower[L'X']]));
+        BOOST_TEST(test(L"x", lower[lower[L'x']]));
+
+        BOOST_TEST(test("x", lower[lower[char_]], 'X'));
+        BOOST_TEST(test("x", lower[lower[char_]], 'x'));
+        BOOST_TEST(test("x", lower[lower[char_('X')]]));
+        BOOST_TEST(test("x", lower[lower[char_('x')]]));
+        
+        BOOST_TEST(test(" ", lower[lower[space]]));
+        BOOST_TEST(test("\t", lower[lower[space]], '\t'));
+        BOOST_TEST(test("\t", lower[lower[space('\t')]]));
+
+        BOOST_TEST(test("X", upper[lower['X']]));
+        BOOST_TEST(test("X", upper[lower['x']]));
+        BOOST_TEST(test(L"X", upper[lower[L'X']]));
+        BOOST_TEST(test(L"X", upper[lower[L'x']]));
+
+        BOOST_TEST(test("X", upper[lower[char_]], 'X'));
+        BOOST_TEST(test("X", upper[lower[char_]], 'x'));
+        BOOST_TEST(test("X", upper[lower[char_('X')]]));
+        BOOST_TEST(test("X", upper[lower[char_('x')]]));
+        
+        BOOST_TEST(test(" ", upper[lower[space]]));
+        BOOST_TEST(test("\t", upper[lower[space]], '\t'));
+        BOOST_TEST(test("\t", upper[lower[space('\t')]]));
+
+        BOOST_TEST(test("X", upper['X']));
+        BOOST_TEST(test("X", upper['x']));
+        BOOST_TEST(test(L"X", upper[L'X']));
+        BOOST_TEST(test(L"X", upper[L'x']));
+
+        BOOST_TEST(test("X", upper[char_], 'X'));
+        BOOST_TEST(test("X", upper[char_], 'x'));
+        BOOST_TEST(test("X", upper[char_('X')]));
+        BOOST_TEST(test("X", upper[char_('x')]));
+        
+        BOOST_TEST(test(" ", upper[space]));
+        BOOST_TEST(test("\t", upper[space], '\t'));
+        BOOST_TEST(test("\t", upper[space('\t')]));
+
+        BOOST_TEST(test("x", lower[upper['X']]));
+        BOOST_TEST(test("x", lower[upper['x']]));
+        BOOST_TEST(test(L"x", lower[upper[L'X']]));
+        BOOST_TEST(test(L"x", lower[upper[L'x']]));
+
+        BOOST_TEST(test("x", lower[upper[char_]], 'X'));
+        BOOST_TEST(test("x", lower[upper[char_]], 'x'));
+        BOOST_TEST(test("x", lower[upper[char_('X')]]));
+        BOOST_TEST(test("x", lower[upper[char_('x')]]));
+        
+        BOOST_TEST(test(" ", lower[upper[space]]));
+        BOOST_TEST(test("\t", lower[upper[space]], '\t'));
+        BOOST_TEST(test("\t", lower[upper[space('\t')]]));
+
+        BOOST_TEST(test("X", upper[upper['X']]));
+        BOOST_TEST(test("X", upper[upper['x']]));
+        BOOST_TEST(test(L"X", upper[upper[L'X']]));
+        BOOST_TEST(test(L"X", upper[upper[L'x']]));
+
+        BOOST_TEST(test("X", upper[upper[char_]], 'X'));
+        BOOST_TEST(test("X", upper[upper[char_]], 'x'));
+        BOOST_TEST(test("X", upper[upper[char_('X')]]));
+        BOOST_TEST(test("X", upper[upper[char_('x')]]));
+        
+        BOOST_TEST(test(" ", upper[upper[space]]));
+        BOOST_TEST(test("\t", upper[upper[space]], '\t'));
+        BOOST_TEST(test("\t", upper[upper[space('\t')]]));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        
+        BOOST_TEST(test("a1- ", lower["a1- "]));
+        BOOST_TEST(test("a1- ", lower["a1- "]));
+        BOOST_TEST(test("a1- ", lower["a1- "]));
+        BOOST_TEST(test("a1- ", lower["A1- "]));
+        
+        BOOST_TEST(test("a1- ", lower[lit], "a1- "));
+        BOOST_TEST(test("a1- ", lower[lit], "A1- "));
+        BOOST_TEST(test("a1- ", lower[lit("a1- ")]));
+        BOOST_TEST(test("a1- ", lower[lit("A1- ")]));
+
+        BOOST_TEST(test("a1- ", lower[lower["a1- "]]));
+        BOOST_TEST(test("a1- ", lower[lower["a1- "]]));
+        BOOST_TEST(test("a1- ", lower[lower["a1- "]]));
+        BOOST_TEST(test("a1- ", lower[lower["A1- "]]));
+        
+        BOOST_TEST(test("a1- ", lower[lower[lit]], "a1- "));
+        BOOST_TEST(test("a1- ", lower[lower[lit]], "A1- "));
+        BOOST_TEST(test("a1- ", lower[lower[lit("a1- ")]]));
+        BOOST_TEST(test("a1- ", lower[lower[lit("A1- ")]]));
+        
+        BOOST_TEST(test("A1- ", upper[lower["a1- "]]));
+        BOOST_TEST(test("A1- ", upper[lower["a1- "]]));
+        BOOST_TEST(test("A1- ", upper[lower["a1- "]]));
+        BOOST_TEST(test("A1- ", upper[lower["A1- "]]));
+        
+        BOOST_TEST(test("A1- ", upper[lower[lit]], "a1- "));
+        BOOST_TEST(test("A1- ", upper[lower[lit]], "A1- "));
+        BOOST_TEST(test("A1- ", upper[lower[lit("a1- ")]]));
+        BOOST_TEST(test("A1- ", upper[lower[lit("A1- ")]]));
+        
+        BOOST_TEST(test("A1- ", upper["a1- "]));
+        BOOST_TEST(test("A1- ", upper["a1- "]));
+        BOOST_TEST(test("A1- ", upper["a1- "]));
+        BOOST_TEST(test("A1- ", upper["A1- "]));
+        
+        BOOST_TEST(test("A1- ", upper[lit], "a1- "));
+        BOOST_TEST(test("A1- ", upper[lit], "A1- "));
+        BOOST_TEST(test("A1- ", upper[lit("a1- ")]));
+        BOOST_TEST(test("A1- ", upper[lit("A1- ")]));
+        
+        BOOST_TEST(test("a1- ", lower[upper["a1- "]]));
+        BOOST_TEST(test("a1- ", lower[upper["a1- "]]));
+        BOOST_TEST(test("a1- ", lower[upper["a1- "]]));
+        BOOST_TEST(test("a1- ", lower[upper["A1- "]]));
+        
+        BOOST_TEST(test("a1- ", lower[upper[lit]], "a1- "));
+        BOOST_TEST(test("a1- ", lower[upper[lit]], "A1- "));
+        BOOST_TEST(test("a1- ", lower[upper[lit("a1- ")]]));
+        BOOST_TEST(test("a1- ", lower[upper[lit("A1- ")]]));
+        
+        BOOST_TEST(test("A1- ", upper[upper["a1- "]]));
+        BOOST_TEST(test("A1- ", upper[upper["a1- "]]));
+        BOOST_TEST(test("A1- ", upper[upper["a1- "]]));
+        BOOST_TEST(test("A1- ", upper[upper["A1- "]]));
+        
+        BOOST_TEST(test("A1- ", upper[upper[lit]], "a1- "));
+        BOOST_TEST(test("A1- ", upper[upper[lit]], "A1- "));
+        BOOST_TEST(test("A1- ", upper[upper[lit("a1- ")]]));
+        BOOST_TEST(test("A1- ", upper[upper[lit("A1- ")]]));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/center_alignment.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/center_alignment.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,79 @@
+//  Copyright (c) 2001-2008 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 <string>
+#include <iterator>
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int 
+main()
+{
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST(test("     x    ", center[char_('x')]));
+        BOOST_TEST(test("     x    ", center[char_], 'x'));
+        BOOST_TEST(test("     x    ", center['x']));
+                              
+        BOOST_TEST(test("     x    ", center(10)[char_('x')]));
+        BOOST_TEST(test("     x    ", center(10)[char_], 'x'));
+        BOOST_TEST(test("     x    ", center(10)['x']));
+
+        BOOST_TEST(test("*****x****", center(10, char_('*'))[char_('x')]));
+        BOOST_TEST(test("*****x****", center(10, '*')[char_], 'x'));
+        BOOST_TEST(test("*****x****", center(10, '*')['x']));
+
+        BOOST_TEST(test("*****x****", center(char_('*'))[char_('x')]));
+        BOOST_TEST(test("*****x****", center(char_('*'))[char_], 'x'));
+        BOOST_TEST(test("*****x****", center(char_('*'))['x']));
+
+        BOOST_TEST(test("     x     ", center(11)[char_('x')]));
+
+        BOOST_TEST(test("    abc   ", center[lit("abc")]));
+        BOOST_TEST(test("    abc   ", center[lit], "abc"));
+                              
+        BOOST_TEST(test("    abc   ", center(10)[lit("abc")]));
+        BOOST_TEST(test("    abc   ", center(10)[lit], "abc"));
+        BOOST_TEST(test("    abc   ", center(10)["abc"]));
+
+        BOOST_TEST(test("****abc***", center(10, char_('*'))[lit("abc")]));
+        BOOST_TEST(test("****abc***", center(10, '*')[lit], "abc"));
+        BOOST_TEST(test("****abc***", center(10, '*')["abc"]));
+
+        BOOST_TEST(test("****abc***", center(char_('*'))[lit("abc")]));
+        BOOST_TEST(test("****abc***", center(char_('*'))[lit], "abc"));
+        BOOST_TEST(test("****abc***", center(char_('*'))["abc"]));
+
+        BOOST_TEST(test("    abc    ", center(11)[lit("abc")]));
+
+        BOOST_TEST(test("    100   ", center[int_(100)]));
+        BOOST_TEST(test("    100   ", center[int_], 100));
+                                
+        BOOST_TEST(test("    100   ", center(10)[int_(100)]));
+        BOOST_TEST(test("    100   ", center(10)[int_], 100));
+                                
+        BOOST_TEST(test("****100***", center(10, char_('*'))[int_(100)]));
+        BOOST_TEST(test("****100***", center(10, '*')[int_], 100));
+                                
+        BOOST_TEST(test("    100    ", center(11)[int_(100)]));
+
+        BOOST_TEST(test("****100***", center(char_('*'))[int_(100)]));
+        BOOST_TEST(test("****100***", center(char_('*'))[int_], 100));
+    }
+    
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/char.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/char.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,151 @@
+//  Copyright (c) 2001-2008 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)
+
+//#define KARMA_FAIL_COMPILATION
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::phoenix;
+    using namespace boost::spirit::arg_names;
+            
+    {
+        using namespace boost::spirit::ascii;
+        
+        BOOST_TEST(test(" ", space));
+        BOOST_TEST(test(L" ", space));
+        BOOST_TEST(!test("\t", space));
+        BOOST_TEST(!test(L"\t", space));
+        
+        BOOST_TEST(test(" ", space(' ')));
+        BOOST_TEST(test(L" ", space(L' ')));
+        BOOST_TEST(test("\t", space('\t')));
+        BOOST_TEST(test(L"\t", space(L'\t')));
+        
+        BOOST_TEST(test(" ", space(' '), '\t'));
+        BOOST_TEST(test(L" ", space(' '), L'\t'));
+        BOOST_TEST(test("\t", space('\t'), ' '));
+        BOOST_TEST(test(L"\t", space('\t'), L' '));
+        
+        BOOST_TEST(test(" ", space, ' '));
+        BOOST_TEST(test(L" ", space, L' '));
+        BOOST_TEST(test("\t", space, '\t'));
+        BOOST_TEST(test(L"\t", space, L'\t'));
+    }
+    
+    {
+        BOOST_TEST(test("x", 'x'));
+        BOOST_TEST(test(L"x", L'x'));
+        BOOST_TEST(!test("x", 'y'));
+        BOOST_TEST(!test(L"x", L'y'));
+        
+        BOOST_TEST(test("x", char_, 'x'));
+        BOOST_TEST(test(L"x", char_, L'x'));
+        BOOST_TEST(!test("x", char_, 'y'));
+        BOOST_TEST(!test(L"x", char_, L'y'));
+        
+        BOOST_TEST(test("x", char_('x')));
+        BOOST_TEST(!test("x", char_('y')));
+        BOOST_TEST(test(L"x", char_(L'x')));
+        BOOST_TEST(!test(L"x", char_(L'y')));
+
+//         BOOST_TEST(test("x", char_("x")));
+//         BOOST_TEST(test(L"x", char_(L"x")));
+
+#if defined(KARMA_FAIL_COMPILATION)
+        BOOST_TEST(test("x", char_));           // anychar without a parameter doesn't make any sense
+#endif
+    }
+
+    {
+        BOOST_TEST(test(L"x", L'x'));
+        BOOST_TEST(test(L"x", 'x'));
+
+        BOOST_TEST(test(L"x", wchar, L'x'));
+        BOOST_TEST(test(L"x", wchar, 'x'));
+
+        BOOST_TEST(test(L"x", wchar(L'x')));
+        BOOST_TEST(test(L"x", wchar('x')));
+    }
+    
+    {
+        using namespace boost::spirit::ascii;
+        
+        BOOST_TEST(test_delimited("x ", 'x', ' '));
+        BOOST_TEST(test_delimited(L"x ", L'x', L' '));
+        BOOST_TEST(!test_delimited("x ", 'y', ' '));
+        BOOST_TEST(!test_delimited(L"x ", L'y', L' '));
+
+        BOOST_TEST(test_delimited("x ", 'x', space));
+        BOOST_TEST(test_delimited(L"x ", L'x', space(L' ')));
+        BOOST_TEST(!test_delimited("x ", 'y', space));
+        BOOST_TEST(!test_delimited(L"x ", L'y', space(L' ')));
+
+        BOOST_TEST(test_delimited("x ", char_, 'x', space));
+        BOOST_TEST(test_delimited(L"x ", char_, L'x', space(L' ')));
+        BOOST_TEST(!test_delimited("x ", char_, 'y', space));
+        BOOST_TEST(!test_delimited(L"x ", char_, L'y', space(L' ')));
+
+        BOOST_TEST(test_delimited("x ", char_('x'), space));
+        BOOST_TEST(!test_delimited("x ", char_('y'), space(L' ')));
+        BOOST_TEST(test_delimited(L"x ", char_(L'x'), space));
+        BOOST_TEST(!test_delimited(L"x ", char_(L'y'), space(L' ')));
+        
+//         BOOST_TEST(test_delimited("x ", char_("x"), space));
+
+#if defined(KARMA_FAIL_COMPILATION)
+        BOOST_TEST(test_delimited("x ", char_, space));   // anychar without a parameter doesn't make any sense
+#endif
+    }
+    
+    {
+        BOOST_TEST(test_delimited(L"x ", L'x', wchar(' ')));
+        BOOST_TEST(test_delimited(L"x ", 'x', wchar(' ')));
+
+        BOOST_TEST(test_delimited(L"x ", wchar, L'x', wchar(' ')));
+        BOOST_TEST(test_delimited(L"x ", wchar, 'x', wchar(' ')));
+
+        BOOST_TEST(test_delimited(L"x ", wchar(L'x'), wchar(' ')));
+        BOOST_TEST(test_delimited(L"x ", wchar('x'), wchar(' ')));
+        
+#if defined(KARMA_FAIL_COMPILATION)
+        BOOST_TEST(test_delimited("x ", char_, space));   // anychar without a parameter doesn't make any sense
+#endif
+    }
+    
+    // action tests
+    {
+        BOOST_TEST(test("x", char_[_1 = val('x')]));
+        BOOST_TEST(test(L"x", char_[_1 = val(L'x')]));
+        BOOST_TEST(!test("x", char_[_1 = val('y')]));
+        BOOST_TEST(!test(L"x", char_[_1 = val(L'y')]));
+    }
+
+    {   // lazy chars
+
+        using namespace boost::phoenix;
+        BOOST_TEST((test("x", char_(val('x')))));
+        BOOST_TEST((test(L"x", char_(val(L'x')))));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/delimiter.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/delimiter.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,55 @@
+//  Copyright (c) 2001-2008 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)
+
+//#define KARMA_FAIL_COMPILATION
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    
+    {
+        BOOST_TEST(test("a b ", delimit[char_('a') << 'b']));
+        BOOST_TEST(test("a*b*", delimit('*')[char_('a') << 'b']));
+
+        BOOST_TEST(test("ab c d", 
+            char_('a') << delimit[char_('b') << 'c'] << 'd'));
+        BOOST_TEST(test("ab*c*d", 
+            char_('a') << delimit('*')[char_('b') << 'c'] << 'd'));
+
+        BOOST_TEST(test_delimited("a b ", delimit[char_('a') << 'b'], char_(' ')));
+        BOOST_TEST(test_delimited("a*b*", delimit('*')[char_('a') << 'b'], char_(' ')));
+
+        BOOST_TEST(test_delimited("a b c d ", 
+            char_('a') << delimit[char_('b') << 'c'] << 'd', char_(' ')));
+        BOOST_TEST(test_delimited("a b*c*d ", 
+            char_('a') << delimit('*')[char_('b') << 'c'] << 'd', char_(' ')));
+    }
+    
+    {
+        BOOST_TEST(test("ab", verbatim[char_('a') << 'b']));
+        BOOST_TEST(test("abcd", 
+            char_('a') << verbatim[char_('b') << 'c'] << 'd'));
+
+        BOOST_TEST(test_delimited("ab ", 
+            verbatim[char_('a') << 'b'], char_(' ')));
+        BOOST_TEST(test_delimited("a bc d ", 
+            char_('a') << verbatim[char_('b') << 'c'] << 'd', char_(' ')));
+    }
+    
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/eps.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/eps.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,31 @@
+//  Copyright (c) 2001-2007 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST(test("", eps));
+    }
+
+    {   // test action
+
+        using namespace boost::phoenix;
+        BOOST_TEST(test("", eps(val(true))));
+        BOOST_TEST(!test("", eps(val(false))));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/format_manip.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/format_manip.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,200 @@
+//  Copyright (c) 2001-2008 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 <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_stream.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <list>
+
+#include <boost/static_assert.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/assign/std/vector.hpp>
+#include <boost/assign/std/list.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename Char, typename Expr>
+bool test(Char const *expected, Expr const& xpr)
+{
+    namespace spirit = boost::spirit;
+    typedef 
+        spirit::traits::is_component<spirit::karma::domain, Expr> 
+    is_component;
+
+    // report invalid expression error as early as possible
+    BOOST_MPL_ASSERT_MSG(is_component::value,
+        xpr_is_not_convertible_to_a_generator, ());
+
+    typedef
+        typename spirit::result_of::as_component<spirit::karma::domain, Expr>::type
+    component;
+    typedef typename component::director director;
+
+    component c = spirit::as_component(spirit::karma::domain(), xpr);
+
+    std::ostringstream ostrm;
+    ostrm << c;
+    return ostrm.good() && ostrm.str() == expected;
+}
+
+template <typename Char, typename Expr, typename Parameter, typename Delimiter>
+bool test(Char const *expected, 
+    boost::spirit::karma::detail::format_manip<Expr, Parameter, Delimiter> const& fm)
+{
+    std::ostringstream ostrm;
+    ostrm << fm;
+    return ostrm.good() && ostrm.str() == expected;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+    using namespace boost::spirit::arg_names;
+    using namespace boost::spirit::karma;
+
+    namespace fusion = boost::fusion;
+    using namespace boost::phoenix;
+
+    {
+        BOOST_TEST(test( "a", 
+            char_[_1 = val('a')]
+        ));
+        BOOST_TEST(test( "a", 
+            format(char_[_1 = val('a')]) 
+        ));
+        BOOST_TEST(test( "a ", 
+            format_delimited(char_[_1 = val('a')], space) 
+        ));
+        BOOST_TEST(test( "a", 
+            format(char_, 'a') 
+        ));
+        BOOST_TEST(test( "a ", 
+            format_delimited(char_, 'a', space) 
+        ));
+    }
+    
+    {
+        BOOST_TEST(test( "ab", 
+            char_[_1 = val('a')] << char_[_1 = val('b')] 
+        ));
+        BOOST_TEST(test( "ab", 
+            format(char_[_1 = val('a')] << char_[_1 = val('b')]) 
+        ));
+        BOOST_TEST(test( "a b ", 
+            format_delimited(char_[_1 = val('a')] << char_[_1 = val('b')], space) 
+        ));
+        
+        fusion::vector<char, char> t('a', 'b');
+
+        BOOST_TEST(test( "ab", 
+            format(char_ << char_, t) 
+        ));
+        BOOST_TEST(test( "a b ", 
+            format_delimited(char_ << char_, t, space) 
+        ));
+    }
+    
+    {
+        BOOST_TEST(test( "abc", 
+            char_[_1 = 'a'] << char_[_1 = 'b'] << char_[_1 = 'c']
+        ));
+        BOOST_TEST(test( "abc", 
+            format(char_('a') << char_('b') << char_('c')) 
+        ));
+        BOOST_TEST(test( "a b c ", 
+            format_delimited(char_('a') << char_('b') << char_('c'), space) 
+        ));
+
+        fusion::vector<char, char, char> t('a', 'b', 'c');
+
+        BOOST_TEST(test( "abc", 
+            format(char_ << char_ << char_, t) 
+        ));
+        BOOST_TEST(test( "a b c ", 
+            format_delimited(char_ << char_ << char_, t, space) 
+        ));
+    }
+
+    {
+        BOOST_TEST(test( "a2", 
+            (char_ << int_)[_1 = 'a', _2 = 2] 
+        ));
+
+        fusion::vector<char, int> t('a', 2);
+
+        BOOST_TEST(test( "a2", 
+            format(char_ << int_, t) 
+        ));
+        BOOST_TEST(test( "a 2 ", 
+            format_delimited(char_ << int_, t, space) 
+        ));
+    }
+    
+    using namespace boost::assign;
+
+    {
+        // output all elements of a vector
+        std::vector<char> v;
+        v += 'a', 'b', 'c';
+        
+        BOOST_TEST(test( "abc", 
+            (*char_)[_1 = v] 
+        ));
+        BOOST_TEST(test( "abc", 
+            format(*char_, v)
+        ));
+        BOOST_TEST(test( "a b c ", 
+            format_delimited(*char_, v, space)
+        ));
+
+        // output a comma separated list of vector elements
+        BOOST_TEST(test( "a, b, c", 
+            (char_ % lit(", "))[_0 = fusion::make_single_view(v)] 
+        ));
+        BOOST_TEST(test( "a, b, c", 
+            format((char_ % lit(", "))[_0 = fusion::make_single_view(v)])
+        ));
+        BOOST_TEST(test( "a , b , c ", 
+            format_delimited((char_ % ',')[_0 = fusion::make_single_view(v)], space)
+        ));
+        BOOST_TEST(test( "a,b,c", 
+            format(char_ % ',', v)
+        ));
+        BOOST_TEST(test( "a , b , c ", 
+            format_delimited(char_ % ',', v, space)
+        ));
+
+        // output all elements of a list
+        std::list<char> l;
+        l += 'a', 'b', 'c';
+        
+//         BOOST_TEST(test( "abc", 
+//             (*char_)[_1 = l] 
+//         ));
+//         BOOST_TEST(test( "abc", 
+//             format((*char_)[_1 = l])
+//         ));
+//         BOOST_TEST(test( "a b c ", 
+//             format_delimited((*char_)[_1 = l], space)
+//         ));
+        BOOST_TEST(test( "abc", 
+            format(*char_, l)
+        ));
+        BOOST_TEST(test( "a b c ", 
+            format_delimited(*char_, l, space)
+        ));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/karma/functor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/functor.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,58 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+struct number_generator : public boost::spirit::karma::functor_base
+{
+    template <typename Context>
+    struct apply
+    {
+        typedef int type;
+    };
+
+    template <typename Parameter, typename Context, typename OutputIterator>
+    bool operator()(Parameter v, Context& ctx, OutputIterator& sink) const
+    {
+        char ch = v % 10 + '0';
+        v /= 10;
+        
+        if (0 != v) 
+            (*this)(v, ctx, sink);
+            
+        *sink = ch;
+        ++sink;
+        return true;
+    }
+};
+
+boost::spirit::karma::functor_generator<number_generator> number;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+    using namespace boost::spirit::karma;
+
+    {
+        BOOST_TEST(test("0", number));
+        BOOST_TEST(test("1234", number, 1234));
+    }
+        
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/grammar.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/grammar.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,63 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+// include this first to make rules have placeholders (e.g. r._1)
+#include <boost/spirit/include/support_argument.hpp>
+
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <string>
+#include <iostream>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+using namespace boost::spirit::karma;
+using namespace boost::spirit::ascii;
+
+typedef spirit_test::output_iterator<char>::type outiter_type;
+
+struct num_list : grammar_def<outiter_type, space_type>
+{
+    num_list()
+    {
+        using boost::spirit::int_;
+        num1 = int_(123);
+        num2 = int_(456);
+        num3 = int_(789);
+        start = num1 << ',' << num2 << ',' << num3;
+    }
+
+    rule<outiter_type, space_type> start, num1, num2, num3;
+};
+
+int
+main()
+{
+    { // simple grammar test
+        num_list def;
+        grammar<num_list> nlist(def);
+        BOOST_TEST(test_delimited("123 , 456 , 789 ", nlist, space));
+    }
+
+    { // direct access to the rules
+
+        num_list def;
+        BOOST_TEST(test_delimited("123 ", def.num1, space));
+        BOOST_TEST(test_delimited("123 , 456 , 789 ", def.start, space));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/karma/grammar_fail.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/grammar_fail.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,46 @@
+/*=============================================================================
+    Copyright (c) 2001-2008 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 <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+
+#include "test.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::karma;
+using namespace boost::spirit::ascii;
+
+struct num_list : grammar_def<char const*, rule<char const*> >
+{
+    num_list()
+    {
+        using boost::spirit::int_;
+        start = int_(1) << ',' << int_(0);
+    }
+
+    rule<char const*, rule<char const*> > start;
+};
+
+// this test must fail compiling
+int main()
+{
+    using boost::make_function_output_iterator;
+    using spirit_test::make_string_appender;
+    
+    std::string generated;
+    
+    num_list def;
+    bool r = generate_delimited(
+                make_function_output_iterator(make_string_appender(generated)), 
+                make_generator(def), char_('%') << '\n');
+
+    return 0;
+}
Added: trunk/libs/spirit/test/karma/int_numerics.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/int_numerics.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,306 @@
+//  Copyright (c) 2001-2008 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)
+
+//#define KARMA_FAIL_COMPILATION
+
+#include <limits>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/mpl/vector.hpp>
+#include <boost/mpl/for_each.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+struct test_minmax
+{
+    template <typename T>
+    void operator()(T) const
+    {
+        using namespace boost::spirit;
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        
+        T minval = (std::numeric_limits<T>::min)();
+        T maxval = (std::numeric_limits<T>::max)();
+        
+        std::string expected_minval = boost::lexical_cast<std::string>(minval); 
+        std::string expected_maxval = boost::lexical_cast<std::string>(maxval);
+        
+        // create a correct generator type from the given integer type
+        typedef typename
+            boost::mpl::if_<
+                boost::mpl::bool_<std::numeric_limits<T>::is_signed>,
+                karma::int_spec<T>,
+                karma::uint_spec<T>
+            >::type
+        int_spec_type;
+        
+        int_spec_type const gen = int_spec_type();
+
+        BOOST_TEST(test(expected_maxval, gen, maxval));
+        BOOST_TEST(test(expected_minval, gen, minval));
+        BOOST_TEST(test(expected_maxval, gen(maxval)));
+        BOOST_TEST(test(expected_minval, gen(minval)));
+
+        BOOST_TEST(test_delimited(expected_maxval + " ", gen, maxval, char(' ')));
+        BOOST_TEST(test_delimited(expected_minval + " ", gen, minval, char(' ')));
+        BOOST_TEST(test_delimited(expected_maxval + " ", gen(maxval), char(' ')));
+        BOOST_TEST(test_delimited(expected_minval + " ", gen(minval), char(' ')));
+
+    // action tests
+        BOOST_TEST(test(expected_maxval, gen[_1 = val(maxval)]));
+        BOOST_TEST(test(expected_minval, gen[_1 = val(minval)]));
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    
+    {
+        using namespace boost::spirit::ascii;
+        
+        ///////////////////////////////////////////////////////////////////////
+        // this is currently ambiguous with character literals
+//         BOOST_TEST(test("0", 0));
+//         BOOST_TEST(test("123", 123));
+//         BOOST_TEST(test("-123", -123));
+
+        BOOST_TEST(test("0", int_, 0));
+        BOOST_TEST(test("123", int_, 123));
+        BOOST_TEST(test("-123", int_, -123));
+
+        BOOST_TEST(test_delimited("0 ", int_, 0, char_(' ')));
+        BOOST_TEST(test_delimited("123 ", int_, 123, char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", int_, -123, char_(' ')));
+
+        BOOST_TEST(test("0", lower[int_], 0));
+        BOOST_TEST(test("123", lower[int_], 123));
+        BOOST_TEST(test("-123", lower[int_], -123));
+
+        BOOST_TEST(test_delimited("0 ", lower[int_], 0, char_(' ')));
+        BOOST_TEST(test_delimited("123 ", lower[int_], 123, char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", lower[int_], -123, char_(' ')));
+
+        BOOST_TEST(test("0", upper[int_], 0));
+        BOOST_TEST(test("123", upper[int_], 123));
+        BOOST_TEST(test("-123", upper[int_], -123));
+
+        BOOST_TEST(test_delimited("0 ", upper[int_], 0, char_(' ')));
+        BOOST_TEST(test_delimited("123 ", upper[int_], 123, char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", upper[int_], -123, char_(' ')));
+
+        ///////////////////////////////////////////////////////////////////////
+        BOOST_TEST(test("0", int_(0)));
+        BOOST_TEST(test("123", int_(123)));
+        BOOST_TEST(test("-123", int_(-123)));
+
+        BOOST_TEST(test_delimited("0 ", int_(0), char_(' ')));
+        BOOST_TEST(test_delimited("123 ", int_(123), char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", int_(-123), char_(' ')));
+
+        BOOST_TEST(test("0", lower[int_(0)]));
+        BOOST_TEST(test("123", lower[int_(123)]));
+        BOOST_TEST(test("-123", lower[int_(-123)]));
+
+        BOOST_TEST(test_delimited("0 ", lower[int_(0)], char_(' ')));
+        BOOST_TEST(test_delimited("123 ", lower[int_(123)], char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", lower[int_(-123)], char_(' ')));
+
+        BOOST_TEST(test("0", upper[int_(0)]));
+        BOOST_TEST(test("123", upper[int_(123)]));
+        BOOST_TEST(test("-123", upper[int_(-123)]));
+
+        BOOST_TEST(test_delimited("0 ", upper[int_(0)], char_(' ')));
+        BOOST_TEST(test_delimited("123 ", upper[int_(123)], char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", upper[int_(-123)], char_(' ')));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        
+        karma::int_spec<int, 10, true> const signed_int =
+            karma::int_spec<int, 10, true>();
+
+        ///////////////////////////////////////////////////////////////////////
+        BOOST_TEST(test(" 0", signed_int, 0));
+        BOOST_TEST(test("+123", signed_int, 123));
+        BOOST_TEST(test("-123", signed_int, -123));
+
+        BOOST_TEST(test_delimited(" 0 ", signed_int, 0, char_(' ')));
+        BOOST_TEST(test_delimited("+123 ", signed_int, 123, char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", signed_int, -123, char_(' ')));
+
+        BOOST_TEST(test(" 0", lower[signed_int], 0));
+        BOOST_TEST(test("+123", lower[signed_int], 123));
+        BOOST_TEST(test("-123", lower[signed_int], -123));
+
+        BOOST_TEST(test_delimited(" 0 ", lower[signed_int], 0, char_(' ')));
+        BOOST_TEST(test_delimited("+123 ", lower[signed_int], 123, char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", lower[signed_int], -123, char_(' ')));
+
+        BOOST_TEST(test(" 0", upper[signed_int], 0));
+        BOOST_TEST(test("+123", upper[signed_int], 123));
+        BOOST_TEST(test("-123", upper[signed_int], -123));
+
+        BOOST_TEST(test_delimited(" 0 ", upper[signed_int], 0, char_(' ')));
+        BOOST_TEST(test_delimited("+123 ", upper[signed_int], 123, char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", upper[signed_int], -123, char_(' ')));
+
+        ///////////////////////////////////////////////////////////////////////
+        BOOST_TEST(test(" 0", signed_int(0)));
+        BOOST_TEST(test("+123", signed_int(123)));
+        BOOST_TEST(test("-123", signed_int(-123)));
+
+        BOOST_TEST(test_delimited(" 0 ", signed_int(0), char_(' ')));
+        BOOST_TEST(test_delimited("+123 ", signed_int(123), char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", signed_int(-123), char_(' ')));
+
+        BOOST_TEST(test(" 0", lower[signed_int(0)]));
+        BOOST_TEST(test("+123", lower[signed_int(123)]));
+        BOOST_TEST(test("-123", lower[signed_int(-123)]));
+
+        BOOST_TEST(test_delimited(" 0 ", lower[signed_int(0)], char_(' ')));
+        BOOST_TEST(test_delimited("+123 ", lower[signed_int(123)], char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", lower[signed_int(-123)], char_(' ')));
+
+        BOOST_TEST(test(" 0", upper[signed_int(0)]));
+        BOOST_TEST(test("+123", upper[signed_int(123)]));
+        BOOST_TEST(test("-123", upper[signed_int(-123)]));
+
+        BOOST_TEST(test_delimited(" 0 ", upper[signed_int(0)], char_(' ')));
+        BOOST_TEST(test_delimited("+123 ", upper[signed_int(123)], char_(' ')));
+        BOOST_TEST(test_delimited("-123 ", upper[signed_int(-123)], char_(' ')));
+    }
+
+    {
+        ///////////////////////////////////////////////////////////////////////
+        using boost::spirit::uint_;
+        using namespace boost::spirit::ascii;
+        
+        BOOST_TEST(test("1234", uint_, 1234));
+        BOOST_TEST(test("ff", hex, 0xff));
+        BOOST_TEST(test("1234", oct, 01234));
+        BOOST_TEST(test("11110000", bin, 0xf0));
+        
+        BOOST_TEST(test_delimited("1234 ", uint_, 1234, char_(' ')));
+        BOOST_TEST(test_delimited("ff ", hex, 0xff, char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", oct, 01234, char_(' ')));
+        BOOST_TEST(test_delimited("11110000 ", bin, 0xf0, char_(' ')));
+        
+        BOOST_TEST(test("1234", lower[uint_], 1234));
+        BOOST_TEST(test("ff", lower[hex], 0xff));
+        BOOST_TEST(test("1234", lower[oct], 01234));
+        BOOST_TEST(test("11110000", lower[bin], 0xf0));
+        
+        BOOST_TEST(test_delimited("1234 ", lower[uint_], 1234, char_(' ')));
+        BOOST_TEST(test_delimited("ff ", lower[hex], 0xff, char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", lower[oct], 01234, char_(' ')));
+        BOOST_TEST(test_delimited("11110000 ", lower[bin], 0xf0, char_(' ')));
+        
+        BOOST_TEST(test("1234", upper[uint_], 1234));
+        BOOST_TEST(test("FF", upper[hex], 0xff));
+        BOOST_TEST(test("1234", upper[oct], 01234));
+        BOOST_TEST(test("11110000", upper[bin], 0xf0));
+        
+        BOOST_TEST(test_delimited("1234 ", upper[uint_], 1234, char_(' ')));
+        BOOST_TEST(test_delimited("FF ", upper[hex], 0xff, char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", upper[oct], 01234, char_(' ')));
+        BOOST_TEST(test_delimited("11110000 ", upper[bin], 0xf0, char_(' ')));
+        
+        // no generator transformation should occur for uint_'s
+        BOOST_TEST(test("1234", upper[upper[uint_]], 1234));
+        BOOST_TEST(test("1234", upper[lower[uint_]], 1234));
+        BOOST_TEST(test("1234", lower[upper[uint_]], 1234));
+        BOOST_TEST(test("1234", lower[lower[uint_]], 1234));
+        
+        BOOST_TEST(test_delimited("1234 ", upper[upper[uint_]], 1234, char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", upper[lower[uint_]], 1234, char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", lower[upper[uint_]], 1234, char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", lower[lower[uint_]], 1234, char_(' ')));
+        
+        BOOST_TEST(test("FF", upper[upper[hex]], 0xff));
+        BOOST_TEST(test("FF", upper[lower[hex]], 0xff));
+        BOOST_TEST(test("ff", lower[upper[hex]], 0xff));
+        BOOST_TEST(test("ff", lower[lower[hex]], 0xff));
+
+        BOOST_TEST(test_delimited("FF ", upper[upper[hex]], 0xff, char_(' ')));
+        BOOST_TEST(test_delimited("FF ", upper[lower[hex]], 0xff, char_(' ')));
+        BOOST_TEST(test_delimited("ff ", lower[upper[hex]], 0xff, char_(' ')));
+        BOOST_TEST(test_delimited("ff ", lower[lower[hex]], 0xff, char_(' ')));
+
+        ///////////////////////////////////////////////////////////////////////
+        BOOST_TEST(test("1234", uint_(1234)));
+        BOOST_TEST(test("ff", hex(0xff)));
+        BOOST_TEST(test("1234", oct(01234)));
+        BOOST_TEST(test("11110000", bin(0xf0)));
+        
+        BOOST_TEST(test_delimited("1234 ", uint_(1234), char_(' ')));
+        BOOST_TEST(test_delimited("ff ", hex(0xff), char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", oct(01234), char_(' ')));
+        BOOST_TEST(test_delimited("11110000 ", bin(0xf0), char_(' ')));
+
+        BOOST_TEST(test("1234", lower[uint_(1234)]));
+        BOOST_TEST(test("ff", lower[hex(0xff)]));
+        BOOST_TEST(test("1234", lower[oct(01234)]));
+        BOOST_TEST(test("11110000", lower[bin(0xf0)]));
+        
+        BOOST_TEST(test_delimited("1234 ", lower[uint_(1234)], char_(' ')));
+        BOOST_TEST(test_delimited("ff ", lower[hex(0xff)], char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", lower[oct(01234)], char_(' ')));
+        BOOST_TEST(test_delimited("11110000 ", lower[bin(0xf0)], char_(' ')));
+        
+        BOOST_TEST(test("1234", upper[uint_(1234)]));
+        BOOST_TEST(test("FF", upper[hex(0xff)]));
+        BOOST_TEST(test("1234", upper[oct(01234)]));
+        BOOST_TEST(test("11110000", upper[bin(0xf0)]));
+        
+        BOOST_TEST(test_delimited("1234 ", upper[uint_(1234)], char_(' ')));
+        BOOST_TEST(test_delimited("FF ", upper[hex(0xff)], char_(' ')));
+        BOOST_TEST(test_delimited("1234 ", upper[oct(01234)], char_(' ')));
+        BOOST_TEST(test_delimited("11110000 ", upper[bin(0xf0)], char_(' ')));
+        
+        BOOST_TEST(test("FF", upper[upper[hex(0xff)]]));
+        BOOST_TEST(test("FF", upper[lower[hex(0xff)]]));
+        BOOST_TEST(test("ff", lower[upper[hex(0xff)]]));
+        BOOST_TEST(test("ff", lower[lower[hex(0xff)]]));
+
+        BOOST_TEST(test_delimited("FF ", upper[upper[hex(0xff)]], char_(' ')));
+        BOOST_TEST(test_delimited("FF ", upper[lower[hex(0xff)]], char_(' ')));
+        BOOST_TEST(test_delimited("ff ", lower[upper[hex(0xff)]], char_(' ')));
+        BOOST_TEST(test_delimited("ff ", lower[lower[hex(0xff)]], char_(' ')));
+    }
+
+// test boundary values
+    typedef boost::mpl::vector<
+#ifdef BOOST_HAS_LONG_LONG
+        boost::long_long_type, boost::ulong_long_type,
+#endif
+        short, unsigned short, 
+        int, unsigned int, 
+        long, unsigned long
+    > integer_types;
+    boost::mpl::for_each<integer_types>(test_minmax());
+    
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/karma/kleene.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/kleene.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,113 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+#include <boost/assign/std/vector.hpp>
+
+#include <boost/spirit/include/support_argument.hpp>
+// #include <boost/spirit/include/support_pack.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/spirit/include/support_unused.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    using namespace boost::spirit;
+    namespace fusion = boost::fusion;
+    
+    {
+        using namespace boost::assign;
+
+        std::vector<char> v;
+        v += 'a', 'b', 'c';
+
+        BOOST_TEST(test("abc", *char_, v));
+        BOOST_TEST(test_delimited("a b c ", *char_, v, ' '));
+    }
+    
+    {
+        using namespace boost::assign;
+
+        std::vector<char> v;
+        
+        // these need to fail, because the return value should be false
+        BOOST_TEST(!test("", +char_, v));
+        BOOST_TEST(!test_delimited("", +char_, v, ' '));
+        
+        v += 'a', 'b', 'c';
+
+        BOOST_TEST(test("abc", +char_, v));
+        BOOST_TEST(test_delimited("a b c ", +char_, v, ' '));
+    }
+    
+    {
+        using namespace boost::assign;
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        
+        std::vector<int> v;
+        v += 10, 20, 30;
+
+        BOOST_TEST(test("102030", *int_, v));
+        BOOST_TEST(test_delimited("10, 20, 30, ", *int_, v, lit(", ")));
+
+        typedef fusion::vector<int> fvec;
+        std::vector<fvec> sv;
+        sv += fvec(10), fvec(20), fvec(30);
+
+        BOOST_TEST(test("10,20,30,", *(int_ << ','), sv));
+        BOOST_TEST(test_delimited("10 , 20 , 30 , ", *(int_ << ','), sv, lit(" ")));
+ 
+        fusion::vector<char, char> cc ('a', 'c');
+        BOOST_TEST(test("ac", char_ << *(char_(' ') << ',') << char_, cc));
+        BOOST_TEST(test_delimited("a c ", 
+            char_ << *(char_(' ') << ',') << char_, cc, " "));
+    }
+    
+    {
+        using namespace boost::assign;
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        
+        std::vector<int> v;
+
+        BOOST_TEST(!test("", +int_, v));
+        BOOST_TEST(!test_delimited("", +int_, v, lit(", ")));
+
+        v += 10, 20, 30;
+
+        BOOST_TEST(test("102030", +int_, v));
+        BOOST_TEST(test_delimited("10, 20, 30, ", +int_, v, lit(", ")));
+
+        typedef fusion::vector<int> fvec;
+        std::vector<fvec> sv;
+        sv += fvec(10), fvec(20), fvec(30);
+
+        BOOST_TEST(test("10,20,30,", +(int_ << ','), sv));
+        BOOST_TEST(test_delimited("10 , 20 , 30 , ", +(int_ << ','), sv, lit(" ")));
+
+        fusion::vector<char, char> cc ('a', 'c');
+        BOOST_TEST(!test("", char_ << +(char_(' ') << ',') << char_, cc));
+        BOOST_TEST(!test_delimited("", 
+            char_ << +(char_(' ') << ',') << char_, cc, " "));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/karma/lazy.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/lazy.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,51 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+    using namespace boost::spirit::karma;
+    using namespace boost::phoenix;
+    using namespace boost::spirit::arg_names;
+
+    {
+        BOOST_TEST(test("123", lazy(val(int_)), 123));
+    }
+
+    {
+        int result = 123;
+        BOOST_TEST(test("123", lazy(val(int_))[_1 = ref(result)]));
+    }
+
+    {
+        typedef spirit_test::output_iterator<char>::type outiter_type;
+        rule<outiter_type, void(std::string)> r;
+
+        r = char_('<') << lazy(_r1) << '>' <<  "</" << lazy(_r1) << '>';
+
+        std::string tag("tag"), foo("foo");
+        BOOST_TEST(test("<tag></tag>", r (ref(tag))));
+        BOOST_TEST(!test("<foo></bar>", r (ref(foo))));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/left_alignment.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/left_alignment.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,70 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int 
+main()
+{
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST(test("x         ", left_align[char_('x')]));
+        BOOST_TEST(test("x         ", left_align[char_], 'x'));
+        BOOST_TEST(test("x         ", left_align['x']));
+        
+        BOOST_TEST(test("x         ", left_align(10)[char_('x')]));
+        BOOST_TEST(test("x         ", left_align(10)[char_], 'x'));
+        BOOST_TEST(test("x         ", left_align(10)['x']));
+
+        BOOST_TEST(test("x*********", left_align(10, char_('*'))[char_('x')]));
+        BOOST_TEST(test("x*********", left_align(10, '*')[char_], 'x'));
+        BOOST_TEST(test("x*********", left_align(10, '*')['x']));
+
+        BOOST_TEST(test("x*********", left_align(char_('*'))[char_('x')]));
+        BOOST_TEST(test("x*********", left_align(char_('*'))[char_], 'x'));
+        BOOST_TEST(test("x*********", left_align(char_('*'))['x']));
+
+        BOOST_TEST(test("abc       ", left_align[lit("abc")]));
+        BOOST_TEST(test("abc       ", left_align[lit], "abc"));
+        
+        BOOST_TEST(test("abc       ", left_align(10)[lit("abc")]));
+        BOOST_TEST(test("abc       ", left_align(10)[lit], "abc"));
+        BOOST_TEST(test("abc       ", left_align(10)["abc"]));
+
+        BOOST_TEST(test("abc*******", left_align(10, char_('*'))[lit("abc")]));
+        BOOST_TEST(test("abc*******", left_align(10, '*')[lit], "abc"));
+        BOOST_TEST(test("abc*******", left_align(10, '*')["abc"]));
+
+        BOOST_TEST(test("abc*******", left_align(char_('*'))[lit("abc")]));
+        BOOST_TEST(test("abc*******", left_align(char_('*'))[lit], "abc"));
+        BOOST_TEST(test("abc*******", left_align(char_('*'))["abc"]));
+
+        BOOST_TEST(test("100       ", left_align[int_(100)]));
+        BOOST_TEST(test("100       ", left_align[int_], 100));
+
+        BOOST_TEST(test("100       ", left_align(10)[int_(100)]));
+        BOOST_TEST(test("100       ", left_align(10)[int_], 100));
+
+        BOOST_TEST(test("100*******", left_align(10, char_('*'))[int_(100)]));
+        BOOST_TEST(test("100*******", left_align(10, '*')[int_], 100));
+
+        BOOST_TEST(test("100*******", left_align(char_('*'))[int_(100)]));
+        BOOST_TEST(test("100*******", left_align(char_('*'))[int_], 100));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/list.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/list.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,66 @@
+//  Copyright (c) 2001-2008 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 <string>
+#include <vector>
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/assign/std/vector.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+
+    using namespace boost::assign;
+    
+    std::vector<char> v;
+    v += 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h';
+    
+    {
+        BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ',', v));
+        BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ", 
+            char_ % ',', v, space));
+    }
+
+    {
+        std::string s ("abcdefgh");
+        BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ',', s));
+        BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ", 
+            char_ % ',', s, space));
+    }
+
+    { // actions
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+
+        BOOST_TEST(test("a,b,c,d,e,f,g,h", (char_ % ',')[_1 = ref(v)]));
+        BOOST_TEST(test_delimited("a , b , c , d , e , f , g , h ", 
+            (char_ % ',')[_1 = ref(v)], space));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/karma/lit.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/lit.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,137 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    
+    {
+        BOOST_TEST(test("a", lit('a')));
+        BOOST_TEST(!test("a", lit('b')));
+        
+        BOOST_TEST(test("abc", "abc"));
+        BOOST_TEST(!test("abcd", "abc"));
+
+        BOOST_TEST(test("abc", lit("abc")));
+        BOOST_TEST(!test("abcd", lit("abc")));
+
+        BOOST_TEST(test("abc", lit, "abc"));
+        BOOST_TEST(!test("abcd", lit, "abc"));
+    }
+    
+    {
+        std::string str("abc");
+        BOOST_TEST(test("abc", lit(str)));
+        BOOST_TEST(!test("abcd", lit(str)));
+
+        BOOST_TEST(test("abc", lit, str));
+        BOOST_TEST(!test("abcd", lit, str));
+
+        BOOST_TEST(test("abc", str));
+        BOOST_TEST(!test("abcd", str));
+
+        std::basic_string<wchar_t> wstr(L"abc");
+        BOOST_TEST(test(L"abc", lit(wstr)));
+        BOOST_TEST(!test(L"abcd", lit(wstr)));
+
+        BOOST_TEST(test(L"abc", lit, wstr));
+        BOOST_TEST(!test(L"abcd", lit, wstr));
+
+        BOOST_TEST(test(L"abc", wstr));
+        BOOST_TEST(!test(L"abcd", wstr));
+    }
+    
+    {
+        BOOST_TEST(test(L"a", lit(L'a')));
+        BOOST_TEST(!test(L"a", lit(L'b')));
+        
+        BOOST_TEST(test(L"abc", L"abc"));
+        BOOST_TEST(test(L"abc", "abc"));
+        BOOST_TEST(!test(L"abcd", L"abc"));
+
+        BOOST_TEST(test(L"abc", lit(L"abc")));
+        BOOST_TEST(test(L"abc", wlit(L"abc")));
+        BOOST_TEST(!test(L"abcd", lit(L"abc")));
+
+        BOOST_TEST(test(L"abc", lit, L"abc"));
+        BOOST_TEST(test(L"abc", wlit, L"abc"));
+        BOOST_TEST(!test(L"abcd", lit, L"abc"));
+
+        BOOST_TEST(test(L"abc", lit, "abc"));
+        BOOST_TEST(test(L"abc", wlit, "abc"));
+        BOOST_TEST(!test(L"abcd", lit, "abc"));
+    }
+    
+    {
+        BOOST_TEST(test_delimited("a ", lit('a'), ' '));
+        BOOST_TEST(!test_delimited("a ", lit('b'), ' '));
+        
+        BOOST_TEST(test_delimited("abc ", "abc", ' '));
+        BOOST_TEST(!test_delimited("abcd ", "abc", ' '));
+
+        BOOST_TEST(test_delimited("abc ", lit("abc"), ' '));
+        BOOST_TEST(!test_delimited("abcd ", lit("abc"), ' '));
+
+        BOOST_TEST(test_delimited("abc ", lit, "abc", ' '));
+        BOOST_TEST(!test_delimited("abcd ", lit, "abc", ' '));
+    }
+    
+    {
+        BOOST_TEST(test_delimited(L"a ", lit(L'a'), ' '));
+        BOOST_TEST(!test_delimited(L"a ", lit(L'b'), ' '));
+        
+        BOOST_TEST(test_delimited(L"abc ", L"abc", ' '));
+        BOOST_TEST(!test_delimited(L"abcd ", L"abc", ' '));
+
+        BOOST_TEST(test_delimited(L"abc ", lit(L"abc"), ' '));
+        BOOST_TEST(test_delimited(L"abc ", wlit(L"abc"), ' '));
+        BOOST_TEST(test_delimited(L"abc ", wlit("abc"), ' '));
+        BOOST_TEST(!test_delimited(L"abcd ", lit(L"abc"), ' '));
+
+        BOOST_TEST(test_delimited(L"abc ", lit, L"abc", ' '));
+        BOOST_TEST(test_delimited(L"abc ", wlit, L"abc", ' '));
+        BOOST_TEST(test_delimited(L"abc ", wlit, "abc", ' '));
+        BOOST_TEST(!test_delimited(L"abcd ", lit, L"abc", ' '));
+    }
+
+    {   // test action
+
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+        using namespace boost::spirit::ascii;
+        
+        std::string str("abc");
+        BOOST_TEST(test("abc", lit[_1 = ref(str)]));
+        BOOST_TEST(test_delimited("abc ", lit[_1 = ref(str)], space));
+    }
+
+    {   // lazy strings
+
+        using namespace boost::phoenix;
+        std::basic_string<char> s("abc");
+        BOOST_TEST((test("abc", lit(val(s)))));
+
+        std::basic_string<wchar_t> ws(L"abc");
+        BOOST_TEST((test(L"abc", lit(ref(ws)))));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/none.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/none.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,32 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using namespace spirit_test;
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+
+    {
+        BOOST_TEST((!test("", none, 1)));
+        BOOST_TEST((!test("", none, "test")));
+    }
+
+    {
+        BOOST_TEST((!test_delimited(" ", none, 1, space)));
+        BOOST_TEST((!test_delimited(" ", none, "test", space)));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/optional.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/optional.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,68 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int main()
+{
+    using namespace spirit_test;
+    using namespace boost::spirit;
+
+    {
+        boost::optional<int> opt;
+        BOOST_TEST(test("", -int_, opt));
+
+        opt = 10;
+        BOOST_TEST(test("10", -int_, opt));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        
+        boost::optional<int> opt;
+        BOOST_TEST(test_delimited("", -int_, opt, space));
+
+        opt = 10;
+        BOOST_TEST(test_delimited("10 ", -int_, opt, space));
+    }
+
+    {   // test action
+        using namespace boost::phoenix;
+        namespace phoenix = boost::phoenix;
+        using namespace boost::spirit::arg_names;
+
+        boost::optional<int> n ;
+        BOOST_TEST(test("", (-int_)[_1 = phoenix::ref(n)]));
+
+        n = 1234;
+        BOOST_TEST(test("1234", (-int_)[_1 = phoenix::ref(n)]));
+    }
+
+    {   // test action
+        using namespace boost::phoenix;
+        namespace phoenix = boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        using namespace boost::spirit::ascii;
+
+        boost::optional<int> n;
+        BOOST_TEST(test_delimited("", (-int_)[_1 = phoenix::ref(n)], space));
+
+        n = 1234;
+        BOOST_TEST(test_delimited("1234 ", (-int_)[_1 = phoenix::ref(n)], space));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/pattern.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/pattern.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,188 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+// include this first to make rules have placeholders (e.g. _r1)
+#include <boost/spirit/include/support_argument.hpp>
+
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_auxiliary.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    using namespace boost;
+    using namespace boost::spirit;
+    using namespace boost::spirit::arg_names;
+    using namespace boost::spirit::karma;
+    using namespace boost::spirit::ascii;
+
+    typedef spirit_test::output_iterator<char>::type outiter_type;
+
+    // basic tests
+    {
+        rule<outiter_type> start;
+
+        start = char_[_1 = 'a'] << int_[_1 = 10] << double_[_1 = 12.4];
+        BOOST_TEST(test("a1012.4", start));
+
+        start = (char_ << int_ << double_)[_1 = 'a', _2 = 10, _3 = 12.4];
+        BOOST_TEST(test("a1012.4", start));
+
+        rule<outiter_type> a, b, c;
+        a = char_[_1 = 'a'];
+        b = int_[_1 = 10];
+        c = double_[_1 = 12.4];
+
+        start = a << b << c;
+        BOOST_TEST(test("a1012.4", start));
+    }
+
+    // basic tests involving a direct parameter
+    {
+        typedef variant<char, int, double> var_type;
+        fusion::vector<unused_type, var_type> v (unused, 'a');
+
+        rule<outiter_type, void(var_type)> start;
+
+        start = (char_ | int_ | double_)[_1 = _r1];
+        BOOST_TEST(test("a", start, v));
+
+        v = fusion::vector<unused_type, var_type>(unused, 10);
+        BOOST_TEST(test("10", start, v));
+        v = fusion::vector<unused_type, var_type>(unused, 12.4);
+        BOOST_TEST(test("12.4", start, v));
+    }
+
+    {
+        rule<outiter_type, void(char, int, double)> start;
+        fusion::vector<unused_type, char, int, double> vec(unused, 'a', 10, 12.4);
+
+        start = char_[_1 = _r1] << int_[_1 = _r2] << double_[_1 = _r3];
+        BOOST_TEST(test("a1012.4", start, vec));
+        BOOST_TEST(test("a1012.4", start('a', 10, 12.4)));
+
+        start = (char_ << int_ << double_)[_1 = _r1, _2 = _r2, _3 = _r3];
+        BOOST_TEST(test("a1012.4", start, vec));
+        BOOST_TEST(test("a1012.4", start('a', 10, 12.4)));
+
+        rule<outiter_type, void(char)> a;
+        rule<outiter_type, void(int)> b;
+        rule<outiter_type, void(double)> c;
+
+        a = char_[_1 = _r1];
+        b = int_[_1 = _r1];
+        c = double_[_1 = _r1];
+        start = a(_r1) << b(_r2) << c(_r3);
+        BOOST_TEST(test("a1012.4", start, vec));
+        BOOST_TEST(test("a1012.4", start('a', 10, 12.4)));
+    }
+
+    // test rule parameter propagation
+    {
+        rule<outiter_type, void(char, int, double)> start;
+        fusion::vector<unused_type, char, int, double> vec(unused, 'a', 10, 12.4);
+
+        start %= char_ << int_ << double_;
+        BOOST_TEST(test("a1012.4", start, vec));
+        BOOST_TEST(test("a1012.4", start('a', 10, 12.4)));
+
+        rule<outiter_type, void(char)> a;
+        rule<outiter_type, void(int)> b;
+        rule<outiter_type, void(double)> c;
+
+        a %= char_ << eps;
+        b %= int_;
+        c %= double_;
+        start = a(_r1) << b(_r2) << c(_r3);
+        BOOST_TEST(test("a1012.4", start, vec));
+        BOOST_TEST(test("a1012.4", start('a', 10, 12.4)));
+    }
+
+    // basic tests with delimiter
+    {
+        rule<outiter_type, space_type> start;
+
+        start = char_[_1 = 'a'] << int_[_1 = 10] << double_[_1 = 12.4];
+        BOOST_TEST(test_delimited("a 10 12.4 ", start, space));
+
+        start = (char_ << int_ << double_)[_1 = 'a', _2 = 10, _3 = 12.4];
+        BOOST_TEST(test_delimited("a 10 12.4 ", start, space));
+
+        rule<outiter_type, space_type> a, b, c;
+        a = char_[_1 = 'a'];
+        b = int_[_1 = 10];
+        c = double_[_1 = 12.4];
+
+        start = a << b << c;
+        BOOST_TEST(test_delimited("a 10 12.4 ", start, space));
+    }
+
+    // locals test
+    {
+        rule<outiter_type, locals<std::string> > start;
+
+        start = lit[_1 = "abc", _a = _1] << int_[_1 = 10] << lit[_1 = _a];
+        BOOST_TEST(test("abc10abc", start));
+    }
+
+     //~ { // alias tests
+         //~ typedef variant<char, int, double> var_type;
+         //~ fusion::vector<unused_type, var_type> v (unused, 'a');
+
+         //~ rule<outiter_type, void(var_type)> d, start;
+
+         //~ d = start.alias();   // d will always track start
+
+         //~ start = (char_ | int_ | double_)[_1 = _r1];
+         //~ BOOST_TEST(test("a", d, v));
+
+         //~ v = fusion::vector<unused_type, var_type>(unused, 10);
+         //~ BOOST_TEST(test("10", d, v));
+         //~ v = fusion::vector<unused_type, var_type>(unused, 12.4);
+         //~ BOOST_TEST(test("12.4", d, v));
+     //~ }
+
+     //~ { // copy tests
+
+         //~ rule<char const*> a, b, c, start;
+
+         //~ a = 'a';
+         //~ b = 'b';
+         //~ c = 'c';
+
+         //~ // The FF is the dynamic equivalent of start = *(a | b | c);
+         //~ start = a;
+         //~ start = start.copy() | b;
+         //~ start = start.copy() | c;
+         //~ start = *(start.copy());
+
+         //~ BOOST_TEST(test("abcabcacb", start));
+
+         //~ // The FF is the dynamic equivalent of start = (a | b) >> (start | b);
+         //~ start = b;
+         //~ start = a | copy(start);
+         //~ start = start.copy() >> (start | b);
+
+         //~ BOOST_TEST(test("aaaabababaaabbb", start));
+         //~ BOOST_TEST(test("aaaabababaaabba", start, false));
+     //~ }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/karma/real_numerics.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/real_numerics.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,448 @@
+//  Copyright (c) 2001-2008 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)
+
+//#define KARMA_FAIL_COMPILATION
+
+#include <limits>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/math/concepts/real_concept.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+//  policy for real_generator, which forces the scientific notation
+template <typename T>
+struct scientific_policy : boost::spirit::karma::real_generator_policies<T>
+{
+    //  we want the numbers always to be in scientific format
+    typedef boost::spirit::karma::real_generator_policies<T> base_type;
+    static int floatfield(T n) { return base_type::scientific; }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  policy for real_generator, which forces the fixed notation
+template <typename T>
+struct fixed_policy : boost::spirit::karma::real_generator_policies<T>
+{
+    typedef boost::spirit::karma::real_generator_policies<T> base_type;
+
+    //  we want the numbers always to be in scientific format
+    static int floatfield(T n) { return base_type::fixed; }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  policy for real_generator, which forces to output trailing zeros in the 
+//  fractional part
+template <typename T>
+struct trailing_zeros_policy 
+  : boost::spirit::karma::real_generator_policies<T>   // 4 digits
+{
+    //  we want the numbers always to contain trailing zeros up to 4 digits in 
+    //  the fractional part
+    static bool const trailing_zeros = true;
+    
+    //  we want to generate up to 4 fractional digits 
+    static unsigned int precision(T n) { return 4; }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  policy for real_generator, which forces the sign to be generated
+template <typename T>
+struct signed_policy 
+  : boost::spirit::karma::real_generator_policies<T>
+{
+    // we want to always have a sign generated
+    static bool const force_sign = true;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//  this is a workaround for the missing lround for the real_concept type
+long lround(boost::math::concepts::real_concept n)
+{
+    if (n >= 0)
+        return boost::math::tools::real_cast<long>(n + 0.5);
+    return boost::math::tools::real_cast<long>(n - 0.5);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//  We need to specialize is_real_lit_tag to allow to use a real_concept as a
+//  literal below
+namespace boost { namespace spirit 
+{
+    template <typename Domain>
+    struct is_real_lit_tag<boost::math::concepts::real_concept, Domain> 
+      : boost::mpl::true_ {};
+}}
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    
+    {
+        ///////////////////////////////////////////////////////////////////////
+        // use the default real_policies
+        BOOST_TEST(test("0.0", double_, 0.0));
+        BOOST_TEST(test("1.0", double_, 1.0));
+        BOOST_TEST(test("1.0", double_, 1.0001));
+        BOOST_TEST(test("1.001", double_, 1.001));
+        BOOST_TEST(test("1.01", double_, 1.010));
+        BOOST_TEST(test("1.1", double_, 1.100));
+        
+        BOOST_TEST(test("1.234e-04", double_, 0.00012345));
+        BOOST_TEST(test("0.001", double_, 0.0012345));
+        BOOST_TEST(test("0.012", double_, 0.012345));
+        BOOST_TEST(test("0.123", double_, 0.12345));
+        BOOST_TEST(test("1.234", double_, 1.2345));
+        BOOST_TEST(test("12.346", double_, 12.346));
+        BOOST_TEST(test("123.46", double_, 123.46));
+        BOOST_TEST(test("1234.5", double_, 1234.5));
+        BOOST_TEST(test("12342.0", double_, 12342.));
+        BOOST_TEST(test("1.234e05", double_, 123420.));
+        
+        BOOST_TEST(test("-1.0", double_, -1.0));
+        BOOST_TEST(test("-1.234", double_, -1.2345));
+        BOOST_TEST(test("-1.235", double_, -1.2346));
+        BOOST_TEST(test("-1234.2", double_, -1234.2));
+        
+        BOOST_TEST(test("1.0", double_(1.0)));
+        BOOST_TEST(test("1.0", double_(1.0001)));
+        BOOST_TEST(test("1.001", double_(1.001)));
+        BOOST_TEST(test("1.01", double_(1.010)));
+        BOOST_TEST(test("1.1", double_(1.100)));
+        
+        BOOST_TEST(test("1.234e-04", double_(0.00012345)));
+        BOOST_TEST(test("0.001", double_(0.0012345)));
+        BOOST_TEST(test("0.012", double_(0.012345)));
+        BOOST_TEST(test("0.123", double_(0.12345)));
+        BOOST_TEST(test("1.234", double_(1.2345)));
+        BOOST_TEST(test("12.346", double_(12.346)));
+        BOOST_TEST(test("123.46", double_(123.46)));
+        BOOST_TEST(test("1234.5", double_(1234.5)));
+        BOOST_TEST(test("12342.0", double_(12342.)));
+        BOOST_TEST(test("1.234e05", double_(123420.)));
+    }
+    
+    {
+        ///////////////////////////////////////////////////////////////////////
+        // test NaN and Inf
+        BOOST_TEST(test("nan", double_, std::numeric_limits<double>::quiet_NaN()));
+        BOOST_TEST(test("-nan", double_, -std::numeric_limits<double>::quiet_NaN()));
+        BOOST_TEST(test("inf", double_, std::numeric_limits<double>::infinity()));
+        BOOST_TEST(test("-inf", double_, -std::numeric_limits<double>::infinity()));
+
+        typedef karma::real_spec<double, signed_policy<double> > signed_type;
+        signed_type const signed_ = signed_type();
+
+        BOOST_TEST(test("+nan", signed_, std::numeric_limits<double>::quiet_NaN()));
+        BOOST_TEST(test("-nan", signed_, -std::numeric_limits<double>::quiet_NaN()));
+        BOOST_TEST(test("+inf", signed_, std::numeric_limits<double>::infinity()));
+        BOOST_TEST(test("-inf", signed_, -std::numeric_limits<double>::infinity()));
+        BOOST_TEST(test(" 0.0", signed_, 0.0));
+        
+        BOOST_TEST(test("+nan", signed_(std::numeric_limits<double>::quiet_NaN())));
+        BOOST_TEST(test("-nan", signed_(-std::numeric_limits<double>::quiet_NaN())));
+        BOOST_TEST(test("+inf", signed_(std::numeric_limits<double>::infinity())));
+        BOOST_TEST(test("-inf", signed_(-std::numeric_limits<double>::infinity())));
+        BOOST_TEST(test(" 0.0", signed_(0.0)));
+    }
+    
+    {
+        ///////////////////////////////////////////////////////////////////////
+        typedef karma::real_spec<double, trailing_zeros_policy<double> > 
+            trailing_zeros_type;
+        trailing_zeros_type const trail_zeros = trailing_zeros_type();
+
+        BOOST_TEST(test("0.0000", trail_zeros, 0.0));
+        BOOST_TEST(test("1.0000", trail_zeros, 1.0));
+        BOOST_TEST(test("1.0001", trail_zeros, 1.0001));
+        BOOST_TEST(test("1.0010", trail_zeros, 1.001));
+        BOOST_TEST(test("1.0100", trail_zeros, 1.010));
+        BOOST_TEST(test("1.1000", trail_zeros, 1.100));
+        
+        BOOST_TEST(test("1.2345e-04", trail_zeros, 0.00012345));
+        BOOST_TEST(test("0.0012", trail_zeros, 0.0012345));
+        BOOST_TEST(test("0.0123", trail_zeros, 0.012345));
+        BOOST_TEST(test("0.1235", trail_zeros, 0.12345));
+        BOOST_TEST(test("1.2345", trail_zeros, 1.2345));
+        BOOST_TEST(test("12.3460", trail_zeros, 12.346));
+        BOOST_TEST(test("123.4600", trail_zeros, 123.46));
+        BOOST_TEST(test("1234.5000", trail_zeros, 1234.5));
+        BOOST_TEST(test("12342.0000", trail_zeros, 12342.));
+        BOOST_TEST(test("1.2342e05", trail_zeros, 123420.));
+        
+        BOOST_TEST(test("-1.0000", trail_zeros, -1.0));
+        BOOST_TEST(test("-1.2345", trail_zeros, -1.2345));
+        BOOST_TEST(test("-1.2346", trail_zeros, -1.2346));
+        BOOST_TEST(test("-1234.2000", trail_zeros, -1234.2));
+        
+        BOOST_TEST(test("1.0000", trail_zeros(1.0)));
+        BOOST_TEST(test("1.0001", trail_zeros(1.0001)));
+        BOOST_TEST(test("1.0010", trail_zeros(1.001)));
+        BOOST_TEST(test("1.0100", trail_zeros(1.010)));
+        BOOST_TEST(test("1.1000", trail_zeros(1.100)));
+        
+        BOOST_TEST(test("1.2345e-04", trail_zeros(0.00012345)));
+        BOOST_TEST(test("0.0012", trail_zeros(0.0012345)));
+        BOOST_TEST(test("0.0123", trail_zeros(0.012345)));
+        BOOST_TEST(test("0.1235", trail_zeros(0.12345)));
+        BOOST_TEST(test("1.2345", trail_zeros(1.2345)));
+        BOOST_TEST(test("12.3460", trail_zeros(12.346)));
+        BOOST_TEST(test("123.4600", trail_zeros(123.46)));
+        BOOST_TEST(test("1234.5000", trail_zeros(1234.5)));
+        BOOST_TEST(test("12342.0000", trail_zeros(12342.)));
+        BOOST_TEST(test("1.2342e05", trail_zeros(123420.)));
+    }
+    
+    {
+        ///////////////////////////////////////////////////////////////////////
+        BOOST_TEST(test_delimited("0.0 ", double_, 0.0, char_(' ')));
+        BOOST_TEST(test_delimited("1.0 ", double_, 1.0, char_(' ')));
+        BOOST_TEST(test_delimited("1.0 ", double_, 1.0001, char_(' ')));
+        BOOST_TEST(test_delimited("1.001 ", double_, 1.001, char_(' ')));
+        BOOST_TEST(test_delimited("1.01 ", double_, 1.010, char_(' ')));
+        BOOST_TEST(test_delimited("1.1 ", double_, 1.100, char_(' ')));
+        
+        BOOST_TEST(test_delimited("1.234e-04 ", double_, 0.00012345, char_(' ')));
+        BOOST_TEST(test_delimited("0.001 ", double_, 0.0012345, char_(' ')));
+        BOOST_TEST(test_delimited("0.012 ", double_, 0.012345, char_(' ')));
+        BOOST_TEST(test_delimited("0.123 ", double_, 0.12345, char_(' ')));
+        BOOST_TEST(test_delimited("1.234 ", double_, 1.2345, char_(' ')));
+        BOOST_TEST(test_delimited("12.346 ", double_, 12.346, char_(' ')));
+        BOOST_TEST(test_delimited("123.46 ", double_, 123.46, char_(' ')));
+        BOOST_TEST(test_delimited("1234.5 ", double_, 1234.5, char_(' ')));
+        BOOST_TEST(test_delimited("12342.0 ", double_, 12342., char_(' ')));
+        BOOST_TEST(test_delimited("1.234e05 ", double_, 123420., char_(' ')));
+        
+        BOOST_TEST(test_delimited("-1.0 ", double_, -1.0, char_(' ')));
+        BOOST_TEST(test_delimited("-1.234 ", double_, -1.2345, char_(' ')));
+        BOOST_TEST(test_delimited("-1.235 ", double_, -1.2346, char_(' ')));
+        BOOST_TEST(test_delimited("-1234.2 ", double_, -1234.2, char_(' ')));
+        
+        BOOST_TEST(test_delimited("1.0 ", double_(1.0), char_(' ')));
+        BOOST_TEST(test_delimited("1.0 ", double_(1.0001), char_(' ')));
+        BOOST_TEST(test_delimited("1.001 ", double_(1.001), char_(' ')));
+        BOOST_TEST(test_delimited("1.01 ", double_(1.010), char_(' ')));
+        BOOST_TEST(test_delimited("1.1 ", double_(1.100), char_(' ')));
+        
+        BOOST_TEST(test_delimited("1.234e-04 ", double_(0.00012345), char_(' ')));
+        BOOST_TEST(test_delimited("0.001 ", double_(0.0012345), char_(' ')));
+        BOOST_TEST(test_delimited("0.012 ", double_(0.012345), char_(' ')));
+        BOOST_TEST(test_delimited("0.123 ", double_(0.12345), char_(' ')));
+        BOOST_TEST(test_delimited("1.234 ", double_(1.2345), char_(' ')));
+        BOOST_TEST(test_delimited("12.346 ", double_(12.346), char_(' ')));
+        BOOST_TEST(test_delimited("123.46 ", double_(123.46), char_(' ')));
+        BOOST_TEST(test_delimited("1234.5 ", double_(1234.5), char_(' ')));
+        BOOST_TEST(test_delimited("12342.0 ", double_(12342.), char_(' ')));
+        BOOST_TEST(test_delimited("1.234e05 ", double_(123420.), char_(' ')));
+    }
+
+    {
+        ///////////////////////////////////////////////////////////////////////
+        // test NaN and Inf
+        BOOST_TEST(test_delimited("nan ", double_, 
+            std::numeric_limits<double>::quiet_NaN(), char_(' ')));
+        BOOST_TEST(test_delimited("-nan ", double_, 
+            -std::numeric_limits<double>::quiet_NaN(), char_(' ')));
+        BOOST_TEST(test_delimited("inf ", double_, 
+            std::numeric_limits<double>::infinity(), char_(' ')));
+        BOOST_TEST(test_delimited("-inf ", double_, 
+            -std::numeric_limits<double>::infinity(), char_(' ')));
+
+        typedef karma::real_spec<double, signed_policy<double> > signed_type;
+        signed_type const signed_ = signed_type();
+
+        BOOST_TEST(test_delimited("+nan ", signed_, 
+            std::numeric_limits<double>::quiet_NaN(), char_(' ')));
+        BOOST_TEST(test_delimited("-nan ", signed_, 
+            -std::numeric_limits<double>::quiet_NaN(), char_(' ')));
+        BOOST_TEST(test_delimited("+inf ", signed_, 
+            std::numeric_limits<double>::infinity(), char_(' ')));
+        BOOST_TEST(test_delimited("-inf ", signed_, 
+            -std::numeric_limits<double>::infinity(), char_(' ')));
+        BOOST_TEST(test_delimited(" 0.0 ", signed_, 0.0, char_(' ')));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        
+        ///////////////////////////////////////////////////////////////////////
+        typedef karma::real_spec<double, scientific_policy<double> > 
+            science_type;
+        science_type const science = science_type();
+        
+        BOOST_TEST(test("0.0e00", science, 0.0));
+        BOOST_TEST(test("1.0e00", science, 1.0));
+        
+        BOOST_TEST(test("1.234e-05", science, 0.000012345));
+        BOOST_TEST(test("1.234e-04", science, 0.00012345));
+        BOOST_TEST(test("1.234e-03", science, 0.0012345));
+        BOOST_TEST(test("1.234e-02", science, 0.012345));
+        BOOST_TEST(test("1.235e-01", science, 0.12345));     // note the rounding error!
+        BOOST_TEST(test("1.234e00", science, 1.2345));
+        BOOST_TEST(test("1.235e01", science, 12.346));
+        BOOST_TEST(test("1.235e02", science, 123.46));
+        BOOST_TEST(test("1.234e03", science, 1234.5));
+        BOOST_TEST(test("1.234e04", science, 12342.));
+        BOOST_TEST(test("1.234e05", science, 123420.));
+
+        BOOST_TEST(test("-1.234e-05", science, -0.000012345));
+        BOOST_TEST(test("-1.234e-04", science, -0.00012345));
+        BOOST_TEST(test("-1.234e-03", science, -0.0012345));
+        BOOST_TEST(test("-1.234e-02", science, -0.012345));
+        BOOST_TEST(test("-1.235e-01", science, -0.12345));   // note the rounding error!
+        BOOST_TEST(test("-1.234e00", science, -1.2345));
+        BOOST_TEST(test("-1.235e01", science, -12.346));
+        BOOST_TEST(test("-1.235e02", science, -123.46));
+        BOOST_TEST(test("-1.234e03", science, -1234.5));
+        BOOST_TEST(test("-1.234e04", science, -12342.));
+        BOOST_TEST(test("-1.234e05", science, -123420.));
+
+        BOOST_TEST(test("1.234E-05", upper[science], 0.000012345));
+        BOOST_TEST(test("1.234E-04", upper[science], 0.00012345));
+        BOOST_TEST(test("1.234E-03", upper[science], 0.0012345));
+        BOOST_TEST(test("1.234E-02", upper[science], 0.012345));
+        BOOST_TEST(test("1.235E-01", upper[science], 0.12345));     // note the rounding error!
+        BOOST_TEST(test("1.234E00", upper[science], 1.2345));
+        BOOST_TEST(test("1.235E01", upper[science], 12.346));
+        BOOST_TEST(test("1.235E02", upper[science], 123.46));
+        BOOST_TEST(test("1.234E03", upper[science], 1234.5));
+        BOOST_TEST(test("1.234E04", upper[science], 12342.));
+        BOOST_TEST(test("1.234E05", upper[science], 123420.));
+
+        BOOST_TEST(test("-1.234E-05", upper[science], -0.000012345));
+        BOOST_TEST(test("-1.234E-04", upper[science], -0.00012345));
+        BOOST_TEST(test("-1.234E-03", upper[science], -0.0012345));
+        BOOST_TEST(test("-1.234E-02", upper[science], -0.012345));
+        BOOST_TEST(test("-1.235E-01", upper[science], -0.12345));   // note the rounding error!
+        BOOST_TEST(test("-1.234E00", upper[science], -1.2345));
+        BOOST_TEST(test("-1.235E01", upper[science], -12.346));
+        BOOST_TEST(test("-1.235E02", upper[science], -123.46));
+        BOOST_TEST(test("-1.234E03", upper[science], -1234.5));
+        BOOST_TEST(test("-1.234E04", upper[science], -12342.));
+        BOOST_TEST(test("-1.234E05", upper[science], -123420.));
+    }
+    
+    {
+        using namespace boost::spirit::ascii;
+        
+        ///////////////////////////////////////////////////////////////////////
+        typedef karma::real_spec<double, fixed_policy<double> > fixed_type;
+        fixed_type const fixed = fixed_type();
+        
+        BOOST_TEST(test("0.0", fixed, 0.0));
+        BOOST_TEST(test("1.0", fixed, 1.0));
+        
+        BOOST_TEST(test("0.0", fixed, 0.000012345));
+        BOOST_TEST(test("0.0", fixed, 0.00012345));
+        BOOST_TEST(test("0.001", fixed, 0.0012345));
+        BOOST_TEST(test("0.012", fixed, 0.012345));
+        BOOST_TEST(test("0.123", fixed, 0.12345));
+        BOOST_TEST(test("1.234", fixed, 1.2345));
+        BOOST_TEST(test("12.345", fixed, 12.345));
+        BOOST_TEST(test("123.45", fixed, 123.45));
+        BOOST_TEST(test("1234.5", fixed, 1234.5));
+        BOOST_TEST(test("12342.0", fixed, 12342.));
+        BOOST_TEST(test("123420.0", fixed, 123420.));
+        BOOST_TEST(test("123420000000000000000.0", fixed, 1.23420e20));
+
+        BOOST_TEST(test("0.0", fixed, -0.000012345));
+        BOOST_TEST(test("0.0", fixed, -0.00012345));
+        BOOST_TEST(test("-0.001", fixed, -0.0012345));
+        BOOST_TEST(test("-0.012", fixed, -0.012345));
+        BOOST_TEST(test("-0.123", fixed, -0.12345));
+        BOOST_TEST(test("-1.234", fixed, -1.2345));
+        BOOST_TEST(test("-12.346", fixed, -12.346));
+        BOOST_TEST(test("-123.46", fixed, -123.46));
+        BOOST_TEST(test("-1234.5", fixed, -1234.5));
+        BOOST_TEST(test("-12342.0", fixed, -12342.));
+        BOOST_TEST(test("-123420.0", fixed, -123420.));
+        BOOST_TEST(test("-123420000000000000000.0", fixed, -1.23420e20));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        
+        ///////////////////////////////////////////////////////////////////////
+        // test NaN and Inf
+        BOOST_TEST(test("NAN", upper[double_], 
+            std::numeric_limits<double>::quiet_NaN()));
+        BOOST_TEST(test("-NAN", upper[double_], 
+            -std::numeric_limits<double>::quiet_NaN()));
+        BOOST_TEST(test("INF", upper[double_], 
+            std::numeric_limits<double>::infinity()));
+        BOOST_TEST(test("-INF", upper[double_], 
+            -std::numeric_limits<double>::infinity()));
+
+        typedef karma::real_spec<double, signed_policy<double> > signed_type;
+        signed_type const signed_ = signed_type();
+
+        BOOST_TEST(test("+NAN", upper[signed_], 
+            std::numeric_limits<double>::quiet_NaN()));
+        BOOST_TEST(test("-NAN", upper[signed_], 
+            -std::numeric_limits<double>::quiet_NaN()));
+        BOOST_TEST(test("+INF", upper[signed_], 
+            std::numeric_limits<double>::infinity()));
+        BOOST_TEST(test("-INF", upper[signed_], 
+            -std::numeric_limits<double>::infinity()));
+        BOOST_TEST(test(" 0.0", upper[signed_], 0.0));
+    }
+
+    {
+        using boost::math::concepts::real_concept;
+        typedef karma::real_spec<real_concept> custom_type;
+        custom_type const custom = custom_type();
+
+        BOOST_TEST(test("0.0", custom, real_concept(0.0)));
+        BOOST_TEST(test("1.0", custom, real_concept(1.0)));
+        BOOST_TEST(test("1.0", custom, real_concept(1.0001)));
+        BOOST_TEST(test("1.001", custom, real_concept(1.001)));
+        BOOST_TEST(test("1.01", custom, real_concept(1.010)));
+        BOOST_TEST(test("1.1", custom, real_concept(1.100)));
+        
+        BOOST_TEST(test("1.234e-04", custom, real_concept(0.00012345)));
+        BOOST_TEST(test("0.001", custom, real_concept(0.0012345)));
+        BOOST_TEST(test("0.012", custom, real_concept(0.012345)));
+        BOOST_TEST(test("0.123", custom, real_concept(0.12345)));
+        BOOST_TEST(test("1.234", custom, real_concept(1.2345)));
+        BOOST_TEST(test("12.346", custom, real_concept(12.346)));
+        BOOST_TEST(test("123.46", custom, real_concept(123.46)));
+        BOOST_TEST(test("1234.5", custom, real_concept(1234.5)));
+        BOOST_TEST(test("12342.0", custom, real_concept(12342.)));
+        BOOST_TEST(test("1.234e05", custom, real_concept(123420.)));
+        
+        BOOST_TEST(test("-1.0", custom, real_concept(-1.0)));
+        BOOST_TEST(test("-1.234", custom, real_concept(-1.2345)));
+        BOOST_TEST(test("-1.235", custom, real_concept(-1.2346)));
+        BOOST_TEST(test("-1234.2", custom, real_concept(-1234.2)));
+        
+        BOOST_TEST(test("1.0", custom(real_concept(1.0))));
+        BOOST_TEST(test("1.0", custom(real_concept(1.0001))));
+        BOOST_TEST(test("1.001", custom(real_concept(1.001))));
+        BOOST_TEST(test("1.01", custom(real_concept(1.010))));
+        BOOST_TEST(test("1.1", custom(real_concept(1.100))));
+        
+        BOOST_TEST(test("1.234e-04", custom(real_concept(0.00012345))));
+        BOOST_TEST(test("0.001", custom(real_concept(0.0012345))));
+        BOOST_TEST(test("0.012", custom(real_concept(0.012345))));
+        BOOST_TEST(test("0.123", custom(real_concept(0.12345))));
+        BOOST_TEST(test("1.234", custom(real_concept(1.2345))));
+        BOOST_TEST(test("12.346", custom(real_concept(12.346))));
+        BOOST_TEST(test("123.46", custom(real_concept(123.46))));
+        BOOST_TEST(test("1234.5", custom(real_concept(1234.5))));
+        BOOST_TEST(test("12342.0", custom(real_concept(12342.))));
+        BOOST_TEST(test("1.234e05", custom(real_concept(123420.))));
+    }
+    
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/right_alignment.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/right_alignment.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,70 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int 
+main()
+{
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST(test("         x", right_align[char_('x')]));
+        BOOST_TEST(test("         x", right_align[char_], 'x'));
+        BOOST_TEST(test("         x", right_align['x']));
+        
+        BOOST_TEST(test("         x", right_align(10)[char_('x')]));
+        BOOST_TEST(test("         x", right_align(10)[char_], 'x'));
+        BOOST_TEST(test("         x", right_align(10)['x']));
+
+        BOOST_TEST(test("*********x", right_align(10, char_('*'))[char_('x')]));
+        BOOST_TEST(test("*********x", right_align(10, '*')[char_], 'x'));
+        BOOST_TEST(test("*********x", right_align(10, '*')['x']));
+
+        BOOST_TEST(test("*********x", right_align(char_('*'))[char_('x')]));
+        BOOST_TEST(test("*********x", right_align(char_('*'))[char_], 'x'));
+        BOOST_TEST(test("*********x", right_align(char_('*'))['x']));
+
+        BOOST_TEST(test("       abc", right_align[lit("abc")]));
+        BOOST_TEST(test("       abc", right_align[lit], "abc"));
+        
+        BOOST_TEST(test("       abc", right_align(10)[lit("abc")]));
+        BOOST_TEST(test("       abc", right_align(10)[lit], "abc"));
+        BOOST_TEST(test("       abc", right_align(10)["abc"]));
+
+        BOOST_TEST(test("*******abc", right_align(10, char_('*'))[lit("abc")]));
+        BOOST_TEST(test("*******abc", right_align(10, '*')[lit], "abc"));
+        BOOST_TEST(test("*******abc", right_align(10, '*')["abc"]));
+
+        BOOST_TEST(test("*******abc", right_align(char_('*'))[lit("abc")]));
+        BOOST_TEST(test("*******abc", right_align(char_('*'))[lit], "abc"));
+        BOOST_TEST(test("*******abc", right_align(char_('*'))["abc"]));
+
+        BOOST_TEST(test("       100", right_align[int_(100)]));
+        BOOST_TEST(test("       100", right_align[int_], 100));
+                                
+        BOOST_TEST(test("       100", right_align(10)[int_(100)]));
+        BOOST_TEST(test("       100", right_align(10)[int_], 100));
+                                
+        BOOST_TEST(test("*******100", right_align(10, char_('*'))[int_(100)]));
+        BOOST_TEST(test("*******100", right_align(10, '*')[int_], 100));
+                                
+        BOOST_TEST(test("*******100", right_align(char_('*'))[int_(100)]));
+        BOOST_TEST(test("*******100", right_align(char_('*'))[int_], 100));
+    }
+    
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/karma/rule_fail.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/rule_fail.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,36 @@
+/*=============================================================================
+    Copyright (c) 2001-2008 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 <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+
+#include "test.hpp"
+
+using namespace boost::spirit;
+using namespace boost::spirit::karma;
+using namespace boost::spirit::ascii;
+
+// this test must fail compiling
+int main()
+{
+    using boost::make_function_output_iterator;
+    using spirit_test::make_string_appender;
+    
+    std::string generated;
+    
+    rule<char const*, rule<char const*> > def;
+    def = int_(1) << ',' << int_(0);
+    
+    bool r = generate_delimited(
+                make_function_output_iterator(make_string_appender(generated)), 
+                def, char_('%') << '\n');
+
+    return 0;
+}
Added: trunk/libs/spirit/test/karma/sequence.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/sequence.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,130 @@
+//  Copyright (c) 2001-2008 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)
+
+// #define KARMA_TEST_COMPILE_FAIL
+
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_string.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_directive.hpp>
+#include <boost/spirit/include/karma_action.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/spirit/include/support_unused.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    namespace fusion = boost::fusion;
+    
+    {
+        {
+            BOOST_TEST(test("xi", char_('x') << char_('i')));
+            BOOST_TEST(!test("xi", char_('x') << char_('o')));
+        }
+
+        {
+            BOOST_TEST(test_delimited("x i ", char_('x') << 'i', char(' ')));
+            BOOST_TEST(!test_delimited("x i ", 
+                char_('x') << char_('o'), char(' ')));
+        }
+
+        {
+            BOOST_TEST(test_delimited("Hello , World ", 
+                lit("Hello") << ',' << "World", char(' ')));
+        }
+        
+        {
+            fusion::vector<char, char, std::string> p ('a', 'b', "cdefg");
+            BOOST_TEST(test("abcdefg", char_ << char_ << lit, p));
+            BOOST_TEST(test_delimited("a b cdefg ", 
+                char_ << char_ << lit, p, char(' ')));
+        }
+
+        {
+            fusion::vector<char, int, char> p ('a', 12, 'c');
+            BOOST_TEST(test("a12c", char_ << int_ << char_, p));
+            BOOST_TEST(test_delimited("a 12 c ", 
+                char_ << int_ << char_, p, char(' ')));
+        }
+
+        {
+            // if all elements of a sequence have unused parameters, the whole 
+            // sequence has an unused parameter as well
+            fusion::vector<char, char> p ('a', 'e');
+            BOOST_TEST(test("abcde", 
+                char_ << (char_('b') << 'c' << 'd') << char_, p));
+            BOOST_TEST(test_delimited("a b c d e ", 
+                char_ << (char_('b') << 'c' << 'd') << char_, p, char(' ')));
+        }
+
+        {
+            // literal generators do not need a parameter
+            fusion::vector<char, char> p('a', 'c');
+            BOOST_TEST(test("abc", char_ << 'b' << char_, p));
+            BOOST_TEST(test_delimited("a b c ", 
+                char_ << 'b' << char_, p, char(' ')));
+        }
+        
+        {
+            using namespace boost::spirit::ascii;
+            
+            BOOST_TEST(test("aa", lower[char_('A') << 'a']));
+            BOOST_TEST(test_delimited("BEGIN END ", 
+                upper[lit("begin") << "end"], char(' ')));
+            BOOST_TEST(!test_delimited("BEGIN END ", 
+                upper[lit("begin") << "nend"], char(' ')));
+
+            BOOST_TEST(test("Aa        ", left_align[char_('A') << 'a']));
+            BOOST_TEST(test("    Aa    ", center[char_('A') << 'a']));
+            BOOST_TEST(test("        Aa", right_align[char_('A') << 'a']));
+        }
+
+        // action tests
+        {
+            using namespace boost::phoenix;
+            using namespace boost::spirit::arg_names;
+            using namespace boost::spirit::ascii;
+
+            BOOST_TEST(test("abcdefg", 
+                (char_ << char_ << lit)[_1 = 'a', _2 = 'b', _3 = "cdefg"]));
+            BOOST_TEST(test_delimited("a b cdefg ", 
+                (char_ << char_ << lit)[_1 = 'a', _2 = 'b', _3 = "cdefg"], 
+                char(' ')));
+
+            BOOST_TEST(test_delimited("a 12 c ", 
+                (char_ << int_(12) << char_)[_1 = 'a', _2 = 'c'], char(' ')));
+
+            char c = 'c';
+            BOOST_TEST(test("abc", 
+                (char_[_1 = 'a'] << 'b' << char_)[_1 = 'x', _2 = ref(c)]));
+            BOOST_TEST(test_delimited("a b c ", 
+                (char_[_1 = 'a'] << 'b' << char_)[_2 = ref(c)], char(' ')));
+
+            BOOST_TEST(test("aa", lower[char_ << 'A'][_1 = 'A']));
+            BOOST_TEST(test("AA", upper[char_ << 'a'][_1 = 'a']));
+
+            BOOST_TEST(test("Aa        ", left_align[char_ << 'a'][_1 = 'A']));
+            BOOST_TEST(test("    Aa    ", center[char_ << 'a'][_1 = 'A']));
+            BOOST_TEST(test("        Aa", right_align[char_ << 'a'][_1 = 'A']));
+        }
+    }
+    
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/karma/test.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/karma/test.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,290 @@
+//  Copyright (c) 2001-2008 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_KARMA_TEST_FEB_23_2007_1221PM)
+#define BOOST_SPIRIT_KARMA_TEST_FEB_23_2007_1221PM
+
+#include <string>
+#include <iterator>
+#include <iostream>
+
+#include <boost/function_output_iterator.hpp>
+#include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_what.hpp>
+
+namespace spirit_test
+{
+
+    ///////////////////////////////////////////////////////////////////////////
+    struct display_type
+    {
+        template<typename T>
+        void operator()(T const &) const
+        {
+            std::cout << typeid(T).name() << std::endl;
+        }
+
+        template<typename T>
+        static void print() 
+        {
+            std::cout << typeid(T).name() << std::endl;
+        }
+    };
+
+    display_type const display = {};
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename String>
+    struct string_appender 
+    {
+        string_appender(String& s) 
+        :   str(s) 
+        {}
+        
+        template <typename T>
+        void operator()(T const &x) const 
+        {
+            str += x;
+        }
+
+        String& str;
+    };
+
+    template <typename String>
+    inline string_appender<String> 
+    make_string_appender(String& str)
+    {
+        return string_appender<String>(str);
+    }
+
+    template <typename Char>
+    struct output_iterator
+    {
+        typedef std::basic_string<Char> string_type;
+        typedef string_appender<string_type> appender_type;
+        typedef boost::function_output_iterator<appender_type> type;
+    };
+    
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Char, typename Generator>
+    inline bool test(Char const *expected, Generator const& g)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<Char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate(make_function_output_iterator(
+            make_string_appender(generated)), g);
+                
+        return result && generated == expected;
+    }
+
+    template <typename Char, typename Generator>
+    inline bool test(std::basic_string<Char> const& expected, Generator const& g)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<Char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate(make_function_output_iterator(
+            make_string_appender(generated)), g);
+                
+        return result && generated == expected;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Char, typename Generator, typename Parameter>
+    inline bool test(Char const *expected, Generator const& g, 
+        Parameter const ¶meter)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<Char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate(make_function_output_iterator(
+            make_string_appender(generated)), g, parameter);
+                
+        return result && generated == expected;
+    }
+
+    template <typename Char, typename Generator, typename Parameter>
+    inline bool test(std::basic_string<Char> const& expected, Generator const& g, 
+        Parameter const ¶meter)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<Char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate(make_function_output_iterator(
+            make_string_appender(generated)), g, parameter);
+                
+        return result && generated == expected;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Char, typename Generator, typename Delimiter>
+    inline bool test_delimited(Char const *expected, Generator const& g, 
+        Delimiter const& d)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<Char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate_delimited(make_function_output_iterator(
+            make_string_appender(generated)), g, d);
+                
+        return result && generated == expected;
+    }
+
+    template <typename Char, typename Generator, typename Delimiter>
+    inline bool test_delimited(std::basic_string<Char> const& expected, 
+        Generator const& g, Delimiter const& d)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<Char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate_delimited(make_function_output_iterator(
+            make_string_appender(generated)), g, d);
+                
+        return result && generated == expected;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Char, typename Generator, typename Parameter,
+        typename Delimiter>
+    inline bool test_delimited(Char const *expected, Generator const& g, 
+        Parameter const ¶meter, Delimiter const& d)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<Char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate_delimited(make_function_output_iterator(
+            make_string_appender(generated)), g, parameter, d);
+                
+        return result && generated == expected;
+    }
+
+    template <typename Char, typename Generator, typename Parameter,
+        typename Delimiter>
+    inline bool test_delimited(std::basic_string<Char> const& expected, 
+        Generator const& g, Parameter const ¶meter, Delimiter const& d)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<Char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate_delimited(make_function_output_iterator(
+            make_string_appender(generated)), g, parameter, d);
+                
+        return result && generated == expected;
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Generator>
+    inline bool 
+    binary_test(char const *expected, std::size_t size, 
+        Generator const& g)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<unsigned char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate(make_function_output_iterator(
+            make_string_appender(generated)), g);
+                
+        return result && !std::memcmp(generated.c_str(), expected, size);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Generator, typename Parameter>
+    inline bool 
+    binary_test(char const *expected, std::size_t size, 
+        Generator const& g, Parameter const ¶meter)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all generators have it:
+        boost::spirit::karma::what(g);
+
+        using boost::make_function_output_iterator;
+        namespace karma = boost::spirit::karma;
+        
+        typedef std::basic_string<unsigned char> string_type;
+        
+        string_type generated;
+
+        bool result = karma::generate(make_function_output_iterator(
+            make_string_appender(generated)), g, parameter);
+                
+        return result && !std::memcmp(generated.c_str(), expected, size);
+    }
+
+}   // namespace spirit_test
+
+#endif // !BOOST_SPIRIT_KARMA_TEST_FEB_23_2007_1221PM
Added: trunk/libs/spirit/test/lex/lexertl1.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/lex/lexertl1.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,72 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+int 
+main()
+{
+    using namespace boost::spirit;
+    using namespace spirit_test;
+
+    // the following test aims at the low level lexer and token_def objects, 
+    // normally not visible to/directly used by the user
+
+    // initialize tokens
+    typedef lex::token_def<std::string> token_def;
+    
+    std::size_t const CCOMMENT = 1;
+    std::size_t const CPPCOMMENT = 2;
+    token_def c_comment ("\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/", CCOMMENT);
+    token_def cpp_comment ("\\/\\/[^\\n\\r]*(\\n|\\r|\\r\\n)", CPPCOMMENT);
+        
+    typedef std::string::iterator base_iterator_type;
+    typedef lex::lexertl_token<base_iterator_type> token_type;
+    typedef lex::lexertl_lexer<token_type> lexer_type;
+    typedef lex::lexer_def<lexer_type> lexer_def;
+
+    {
+        // initialize lexer
+        lexer_def def;
+        def.self = c_comment;
+        def.self += cpp_comment;
+        
+        // test lexer for two different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+    }
+    
+    {
+        // initialize lexer
+        lexer_def def;
+        def.self = c_comment | cpp_comment;
+        
+        // test lexer for two different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+    }
+    
+    {
+        // initialize lexer
+        lexer_def def;
+        def.self = token_def('+') | '-' | c_comment;
+        def.self += '*' | cpp_comment;
+        
+        // test lexer for two different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+        BOOST_TEST(test (lex, "+", '+'));
+        BOOST_TEST(test (lex, "-", '-'));
+        BOOST_TEST(test (lex, "*", '*'));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/lex/lexertl2.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/lex/lexertl2.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,96 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include <string>
+
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// a simple lexer class
+template <typename Lexer>
+struct lexertl_test : boost::spirit::lex::lexer_def<Lexer>
+{
+    typedef boost::spirit::lex::token_def<std::string> token_def;
+
+    static std::size_t const CCOMMENT = 1;
+    static std::size_t const CPPCOMMENT = 2;
+    
+    template <typename Self>
+    void def(Self& self)
+    {
+        c_comment = token_def("\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/", CCOMMENT);
+        cpp_comment = token_def("\\/\\/[^\\n\\r]*(\\n|\\r|\\r\\n)", CPPCOMMENT);
+        
+        self = c_comment;
+        self += cpp_comment;
+    }
+
+    token_def c_comment, cpp_comment;
+};
+
+template <typename Lexer>
+struct wlexertl_test : boost::spirit::lex::lexer_def<Lexer>
+{
+    typedef 
+        boost::spirit::lex::token_def<std::basic_string<wchar_t>, wchar_t> 
+    token_def;
+
+    static std::size_t const CCOMMENT = 1;
+    static std::size_t const CPPCOMMENT = 2;
+    
+    template <typename Self>
+    void def(Self& self)
+    {
+        c_comment = token_def(L"\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/", CCOMMENT);
+        cpp_comment = token_def(L"\\/\\/[^\\n\\r]*(\\n|\\r|\\r\\n)", CPPCOMMENT);
+        
+        self = c_comment;
+        self += cpp_comment;
+    }
+
+    token_def c_comment, cpp_comment;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int 
+main()
+{
+    using namespace boost::spirit;
+    using namespace spirit_test;
+
+    // the following test aims at the low level lexer_ and token_ objects, 
+    // normally not visible/used by the user
+    {
+        // initialize lexer
+        typedef std::string::iterator base_iterator_type;
+        typedef lex::lexertl_token<base_iterator_type> token_type;
+        typedef lex::lexertl_lexer<token_type> lexer_type;
+        typedef lexertl_test<lexer_type> lexer_def;
+        
+        // test lexer for two different input strings
+        lexer_def def;
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", lexer_def::CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", lexer_def::CPPCOMMENT));
+    }
+    
+    {
+        // initialize lexer
+        typedef std::basic_string<wchar_t>::iterator base_iterator_type;
+        typedef lex::lexertl_token<base_iterator_type> token_type;
+        typedef lex::lexertl_lexer<token_type> lexer_type;
+        typedef wlexertl_test<lexer_type> lexer_def;
+        
+        // test lexer for two different input strings
+        lexer_def def;
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, L"/* this is a comment */", lexer_def::CCOMMENT));
+        BOOST_TEST(test (lex, L"// this is a comment as well\n", lexer_def::CPPCOMMENT));
+    }
+    
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/lex/lexertl3.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/lex/lexertl3.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,78 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+int 
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::lex;
+    using namespace spirit_test;
+
+    // initialize tokens
+    typedef lex::token_def<std::string> token_def;
+    
+    std::size_t const CCOMMENT = 1;
+    std::size_t const CPPCOMMENT = 2;
+    token_def c_comment ("\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/", CCOMMENT);
+    token_def cpp_comment ("\\/\\/[^\\n\\r]*(\\n|\\r|\\r\\n)", CPPCOMMENT);
+    token_def ws_tok ("[\\v\\f\\n\\r]*");
+    
+    typedef std::string::iterator base_iterator_type;    
+    typedef lex::lexertl_token<base_iterator_type> token_type;
+    typedef lex::lexertl_lexer<token_type> lexer_type;
+    
+    typedef lexer_type::token_set token_set;
+    typedef lex::lexer_def<lexer_type> lexer_def;
+
+    token_set s;
+    lexer_def def;
+    
+    {
+        // initialize lexer
+        std::string str("def");
+        lexer_def def;
+        def.self = c_comment;
+        def.self += cpp_comment | '1' | '2' | '3' | "abc" | str;
+        def.self += token_def(' ') | '\t' | ws_tok;
+
+        // test lexer for two different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+        BOOST_TEST(test (lex, "\n\n\v\f\r", ws_tok.id()));
+        BOOST_TEST(test (lex, " ", ' '));
+        BOOST_TEST(test (lex, "2", '2'));
+        BOOST_TEST(test (lex, "abc"));
+        BOOST_TEST(test (lex, "def"));
+    }
+    
+    {
+        // init a token set
+        token_set ws;
+        ws = token_def(' ') | '\t' | ws_tok;
+
+        // initialize lexer
+        lexer_def def;
+        def.self = c_comment;
+        def.self += cpp_comment | '1' | '2' | '3';
+        def.self("WHITESPACE") = ws;
+
+        // test lexer for two different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+        BOOST_TEST(test (lex, "2", '2'));
+        BOOST_TEST(!test (lex, "\n\n\v\f\r", ws_tok.id()));
+        BOOST_TEST(test (lex, " ", ' ', "WHITESPACE"));
+        BOOST_TEST(test (lex, "\n\n\v\f\r", ws_tok.id(), "WHITESPACE"));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/lex/lexertl4.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/lex/lexertl4.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,96 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+int 
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::lex;
+    using namespace spirit_test;
+
+    // initialize tokens
+    typedef lex::token_def<std::string> token_def;
+    
+    std::size_t const CCOMMENT = 1;
+    std::size_t const CPPCOMMENT = 2;
+    std::size_t const TOKEN_ID_ABC = 1000;
+    std::size_t const TOKEN_ID_STR = 1001;
+    std::size_t const TOKEN_ID_WS = 1002;
+    
+    token_def c_comment ("\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/", CCOMMENT);
+    token_def cpp_comment ("\\/\\/[^\\n\\r]*(\\n|\\r|\\r\\n)", CPPCOMMENT);
+    token_def ws_tok ("[\\v\\f\\n\\r]*", TOKEN_ID_WS);
+    
+    typedef std::string::iterator base_iterator_type;    
+    typedef lex::lexertl_token<base_iterator_type> token_type;
+    typedef lex::lexertl_lexer<token_type> lexer_type;
+    
+    typedef lexer_type::token_set token_set;
+    typedef lex::lexer_def<lexer_type> lexer_def;
+
+    token_set s;
+    std::string str("def");
+
+    {
+        // initialize lexer
+        lexer_def def;
+        def.self.add
+            (c_comment)(cpp_comment) 
+            ('1')('2')('3')
+            ("abc", TOKEN_ID_ABC)
+            (str, TOKEN_ID_STR)
+        ;
+        def.self += token_def(' ') | '\t' | ws_tok;
+
+        // test lexer for different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+        BOOST_TEST(test (lex, "\n\n\v\f\r", ws_tok.id()));
+        BOOST_TEST(test (lex, " ", ' '));
+        BOOST_TEST(test (lex, "2", '2'));
+        BOOST_TEST(test (lex, "abc", TOKEN_ID_ABC));
+        BOOST_TEST(test (lex, "def", TOKEN_ID_STR));
+    }
+    
+    {
+        // init a token set
+        token_set ws;
+        ws.add
+            (' ')('\t')
+            (ws_tok)
+        ;
+
+        // initialize lexer
+        lexer_def def;
+        def.self.add
+            (c_comment)(cpp_comment) 
+            ('1')('2')('3')
+            ("abc", TOKEN_ID_ABC)
+            (str, TOKEN_ID_STR)
+        ;
+
+        def.self("WHITESPACE").add(ws);
+
+        // test lexer for different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+        BOOST_TEST(test (lex, "2", '2'));
+        BOOST_TEST(test (lex, "abc", TOKEN_ID_ABC));
+        BOOST_TEST(test (lex, "def", TOKEN_ID_STR));
+
+        BOOST_TEST(!test (lex, "\n\n\v\f\r", TOKEN_ID_WS));
+        BOOST_TEST(test (lex, " ", ' ', "WHITESPACE"));
+        BOOST_TEST(test (lex, "\n\n\v\f\r", TOKEN_ID_WS, "WHITESPACE"));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/lex/lexertl5.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/lex/lexertl5.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,115 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  test pattern definition capabilities
+int 
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::lex;
+    using namespace spirit_test;
+
+    // initialize tokens
+    typedef lex::token_def<std::string> token_def;
+    
+    std::size_t const CCOMMENT = 1;
+    std::size_t const CPPCOMMENT = 2;
+    std::size_t const TOKEN_ID_ABC = 1000;
+    std::size_t const TOKEN_ID_STR = 1001;
+    std::size_t const TOKEN_ID_WS = 1002;
+    
+    typedef std::string::iterator base_iterator_type;    
+    typedef lex::lexertl_token<base_iterator_type> token_type;
+    typedef lex::lexertl_lexer<token_type> lexer_type;
+    
+    typedef lexer_type::token_set token_set;
+    typedef lex::lexer_def<lexer_type> lexer_def;
+
+    token_set s;
+    std::string str("def");
+
+    {
+        // initialize lexer
+        lexer_def def;
+        
+        def.self.add_pattern
+            ("CCOMMENT", "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/")
+            ("CPPCOMMENT", "\\/\\/[^\\n\\r]*(\\n|\\r|\\r\\n)")
+            ("WS", "[\\v\\f\\n\\r]*")
+        ;
+        
+        token_def c_comment ("{CCOMMENT}", CCOMMENT);
+        token_def cpp_comment ("{CPPCOMMENT}", CPPCOMMENT);
+        token_def ws_tok ("{WS}");
+
+        def.self.add
+            (c_comment)(cpp_comment) 
+            ('1')('2')('3')
+            ("abc", TOKEN_ID_ABC)
+            (str, TOKEN_ID_STR)
+        ;
+        def.self += token_def(' ') | '\t' | ws_tok;
+
+        // test lexer for different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+        BOOST_TEST(test (lex, "\n\n\v\f\r", ws_tok.id()));
+        BOOST_TEST(test (lex, " ", ' '));
+        BOOST_TEST(test (lex, "2", '2'));
+        BOOST_TEST(test (lex, "abc", TOKEN_ID_ABC));
+        BOOST_TEST(test (lex, "def", TOKEN_ID_STR));
+    }
+    
+    {
+        // initialize lexer
+        lexer_def def;
+
+        def.self.add_pattern
+            ("CCOMMENT", "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/")
+            ("CPPCOMMENT", "\\/\\/[^\\n\\r]*(\\n|\\r|\\r\\n)")
+            ("WS", "[\\v\\f\\n\\r]*")
+        ;
+        
+        token_def c_comment ("{CCOMMENT}", CCOMMENT);
+        token_def cpp_comment ("{CPPCOMMENT}", CPPCOMMENT);
+        token_def ws_tok ("{WS}");
+
+        // init a token set
+        token_set ws;
+        ws.add
+            (' ')('\t')
+            (ws_tok, TOKEN_ID_WS)
+        ;
+
+        def.self.add
+            (c_comment)(cpp_comment) 
+            ('1')('2')('3')
+            ("abc", TOKEN_ID_ABC)
+            (str, TOKEN_ID_STR)
+        ;
+
+        def.self("WHITESPACE").add(ws);
+
+        // test lexer for different input strings
+        lex::lexer<lexer_def> lex(def);
+        BOOST_TEST(test (lex, "/* this is a comment */", CCOMMENT));
+        BOOST_TEST(test (lex, "// this is a comment as well\n", CPPCOMMENT));
+        BOOST_TEST(test (lex, "2", '2'));
+        BOOST_TEST(test (lex, "abc", TOKEN_ID_ABC));
+        BOOST_TEST(test (lex, "def", TOKEN_ID_STR));
+
+        BOOST_TEST(!test (lex, "\n\n\v\f\r", TOKEN_ID_WS));
+        BOOST_TEST(test (lex, " ", ' ', "WHITESPACE"));
+        BOOST_TEST(test (lex, "\n\n\v\f\r", TOKEN_ID_WS, "WHITESPACE"));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/lex/state_switcher_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/lex/state_switcher_test.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,92 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/lex_lexer_lexertl.hpp>
+#include "test_parser.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//  Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct switch_state_tokens : boost::spirit::lex::lexer_def<Lexer>
+{
+    template <typename Self>
+    void def (Self& self)
+    {
+        // define tokens and associate them with the lexer
+        identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+        self = identifier;
+        
+        // any token definition to be used as the skip parser during parsing 
+        // has to be associated with a separate lexer state (here 'WS') 
+        white_space = "[ \\t\\n]+";
+        self("WS") = white_space;
+
+        separators = "[,;]";
+        self("SEP") = separators;
+    }
+    
+    boost::spirit::lex::token_def<> identifier, white_space, separators;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int 
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::qi;
+    using namespace boost::spirit::lex;
+    using namespace spirit_test;
+
+    typedef std::string::iterator base_iterator_type;
+    typedef boost::spirit::lex::lexertl_token<base_iterator_type> token_type;
+    typedef boost::spirit::lex::lexertl_lexer<token_type> lexer_type;
+
+    {
+        // the tokens class will be initialized inside the test_parser function
+        switch_state_tokens<lexer_type> tokens;
+        
+        BOOST_TEST(test_parser("ident", tokens.identifier, tokens));
+        BOOST_TEST(!test_parser("ident", set_state("WS") >> tokens.identifier, tokens));
+        BOOST_TEST(!test_parser("ident", in_state("WS")[tokens.identifier], tokens));
+
+        BOOST_TEST(test_parser("\t \n", set_state("WS") >> tokens.white_space, tokens));
+        BOOST_TEST(test_parser("\t \n", in_state("WS")[tokens.white_space], tokens));
+        BOOST_TEST(!test_parser("\t \n", tokens.white_space, tokens));
+    }
+    
+    {
+        // the tokens class will be initialized inside the test_parser function
+        switch_state_tokens<lexer_type> tokens;
+        
+        BOOST_TEST(test_parser(",ident", tokens.identifier, tokens, 
+            in_state("SEP")[tokens.separators]));
+        BOOST_TEST(!test_parser(";ident", set_state("WS") >> tokens.identifier, 
+            tokens, in_state("SEP")[tokens.separators]));
+        BOOST_TEST(!test_parser(",ident", in_state("WS")[tokens.identifier], 
+            tokens, in_state("SEP")[tokens.separators]));
+
+        BOOST_TEST(test_parser(",\t \n", set_state("WS") >> tokens.white_space, 
+            tokens, in_state("SEP")[tokens.separators]));
+        BOOST_TEST(test_parser(";\t \n", in_state("WS")[tokens.white_space], 
+            tokens, in_state("SEP")[tokens.separators]));
+        BOOST_TEST(!test_parser(",\t \n", tokens.white_space, tokens, 
+            in_state("SEP")[tokens.separators]));
+    }
+    
+    {
+        // the tokens class will be initialized inside the test_parser function
+        switch_state_tokens<lexer_type> tokens;
+        
+        BOOST_TEST(test_parser("ident\t \n", 
+            tokens.identifier >> set_state("WS") >> tokens.white_space, tokens));
+        BOOST_TEST(test_parser("\t \nident", 
+            in_state("WS")[tokens.white_space] >> tokens.identifier, tokens));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/lex/test.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/lex/test.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,89 @@
+//  Copyright (c) 2001-2008 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_LEX_TEST_MAR_23_2007_0721PM)
+#define BOOST_SPIRIT_LEX_TEST_MAR_23_2007_0721PM
+
+namespace spirit_test
+{
+    ///////////////////////////////////////////////////////////////////////////
+    struct display_type
+    {
+        template<typename T>
+        void operator()(T const &) const
+        {
+            std::cout << typeid(T).name() << std::endl;
+        }
+
+        template<typename T>
+        static void print() 
+        {
+            std::cout << typeid(T).name() << std::endl;
+        }
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
+    display_type const display = {};
+    
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Iterator>
+    inline boost::iterator_range<Iterator> const& 
+    get_iterpair(boost::iterator_range<Iterator> const& itp)
+    {
+        return itp;
+    }
+    
+    template <typename Iterator, BOOST_VARIANT_ENUM_PARAMS(typename T)>
+    inline boost::iterator_range<Iterator> const& 
+    get_iterpair(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& v)
+    {
+        return get<boost::iterator_range<Iterator> >(v);
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Lexer, typename Char>
+    inline bool 
+    test(Lexer& lex, Char const* input, std::size_t token_id = 0, 
+        Char const* state = NULL)
+    {
+        typedef typename Lexer::iterator_type iterator_type;
+        typedef std::basic_string<Char> string_type;
+        
+        string_type str(input);
+        typename string_type::iterator it = str.begin();
+        
+        iterator_type first = lex.begin(it, str.end());
+        iterator_type last = lex.end();
+        
+        bool r = true;
+        
+        if (NULL != state) {
+            std::size_t stateid = lex.map_state(state);
+            r = r && (static_cast<unsigned>(~0) != stateid);
+            first.set_state(stateid);
+        }
+            
+        r = r && lex;
+        r = r && first != last;
+        
+        if (token_id != 0)
+            r = r && (*first).id() == token_id;
+        else
+            r = r && (*first).id() != 0;
+            
+        using namespace boost;
+        
+        typedef typename Lexer::iterator_type::base_iterator_type iterator;
+        typedef iterator_range<iterator> iterpair_type;
+        iterpair_type const& ip = get_iterpair<iterator>((*first).value());
+
+        r = r && string_type(ip.begin(), ip.end()) == str;
+        return r && first != last && ++first == last;
+    }
+}
+
+#endif
+
+
Added: trunk/libs/spirit/test/lex/test_parser.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/lex/test_parser.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,67 @@
+/*=============================================================================
+    Copyright (c) 2001-2008 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_TEST_PARSER_SEP_24_2007_0558PM)
+#define BOOST_SPIRIT_TEST_PARSER_SEP_24_2007_0558PM
+
+#include <boost/spirit/include/qi_parse.hpp>
+#include <boost/spirit/include/qi_what.hpp>
+
+namespace spirit_test
+{
+    template <typename Char, typename Parser, typename Tokens>
+    bool test_parser(Char const* in, Parser const& p, Tokens& tokens, 
+        bool full_match = true)
+    {
+        boost::spirit::lex::lexer<Tokens> lex(tokens);
+
+        // we don't care about the result of the "what" function.
+        // we only care that all parsers have it:
+        boost::spirit::qi::what(p);
+
+        std::string str (in);
+        std::string::iterator it_in = str.begin();
+        std::string::iterator end_in = str.end();
+
+        typedef typename 
+            boost::spirit::lex::lexer<Tokens>::iterator_type 
+        iterator_type;
+        
+        iterator_type iter = lex.begin(it_in, end_in);
+        iterator_type end = lex.end();
+            
+        return boost::spirit::qi::parse(iter, end, p)
+            && (!full_match || (iter == end));
+    }
+
+    template <typename Char, typename Parser, typename Tokens, typename Skipper>
+    bool test_parser(Char const* in, Parser const& p, Tokens& tokens,
+          Skipper const& s, bool full_match = true)
+    {
+        boost::spirit::lex::lexer<Tokens> lex(tokens);
+
+        // we don't care about the result of the "what" function.
+        // we only care that all parsers have it:
+        boost::spirit::qi::what(p);
+
+        std::string str (in);
+        std::string::iterator it_in = str.begin();
+        std::string::iterator end_in = str.end();
+
+        typedef typename 
+            boost::spirit::lex::lexer<Tokens>::iterator_type 
+        iterator_type;
+        
+        iterator_type iter = lex.begin(it_in, end_in);
+        iterator_type end = lex.end();
+
+        return boost::spirit::qi::phrase_parse(iter, end, p, s)
+            && (!full_match || (iter == end));
+    }
+
+}
+
+#endif
Added: trunk/libs/spirit/test/qi/alternative.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/alternative.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,87 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/variant.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST((test("a", char_ | char_)));
+        BOOST_TEST((test("x", char_('x') | char_('i'))));
+        BOOST_TEST((test("i", char_('x') | char_('i'))));
+        BOOST_TEST((!test("z", char_('x') | char_('o'))));
+        BOOST_TEST((test("rock", lit("rock") | lit("roll"))));
+        BOOST_TEST((test("roll", lit("rock") | lit("roll"))));
+        BOOST_TEST((test("rock", lit("rock") | int_)));
+        BOOST_TEST((test("12345", lit("rock") | int_)));
+    }
+
+    {
+        boost::variant<unused_type, int, char> v;
+
+        BOOST_TEST((test_attr("12345", lit("rock") | int_ | char_, v)));
+        BOOST_TEST(boost::get<int>(v) == 12345);
+
+        BOOST_TEST((test_attr("rock", lit("rock") | int_ | char_, v)));
+//        BOOST_TEST(boost::get<std::string>(&v) == 0);
+        BOOST_TEST(boost::get<int>(&v) == 0);
+        BOOST_TEST(boost::get<char>(&v) == 0);
+
+        BOOST_TEST((test_attr("x", lit("rock") | int_ | char_, v)));
+        BOOST_TEST(boost::get<char>(v) == 'x');
+    }
+
+    {   // test action
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        namespace phx = boost::phoenix;
+
+        boost::variant<unused_type, int, char> v;
+
+        BOOST_TEST((test("12345", (lit("rock") | int_ | char_)[phx::ref(v) = _1])));
+        BOOST_TEST(boost::get<int>(v) == 12345);
+    }
+
+    {
+        boost::variant<unused_type> v;
+        BOOST_TEST((test("rock", lit("rock") | char_('x'))));
+    }
+
+    {
+        // test if alternatives with all components having unused
+        // attributes return attributes them self
+        using namespace boost::fusion;
+
+        vector<char, char> v;
+        BOOST_TEST((test_attr("abc",
+            char_ >> (omit[char_] | omit[char_]) >> char_, v)));
+        BOOST_TEST((at_c<0>(v) == 'a'));
+        BOOST_TEST((at_c<1>(v) == 'c'));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/and_predicate.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/and_predicate.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,27 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST((test("1234", &int_, false)));
+        BOOST_TEST((!test("abcd", &int_)));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/binary.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/binary.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,110 @@
+//  Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/qi_binary.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+
+#include <boost/cstdint.hpp>
+
+#include "test.hpp"
+
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::phoenix;
+    using namespace boost::spirit::arg_names;
+
+    boost::uint8_t uc;
+    boost::uint16_t us;
+    boost::uint32_t ui;
+#ifdef BOOST_HAS_LONG_LONG
+    boost::uint64_t ul;
+#endif
+
+    {   // test native endian binaries
+#ifdef BOOST_LITTLE_ENDIAN
+        BOOST_TEST(test_attr("\x01", byte, uc) && uc == 0x01);
+        BOOST_TEST(test_attr("\x01\x02", word, us) && us == 0x0201);
+        BOOST_TEST(test_attr("\x01\x02\x03\x04", dword, ui) && ui == 0x04030201);
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(test_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul) &&
+            ul == 0x0807060504030201LL);
+#endif
+#else
+        BOOST_TEST(test_attr("\x01", byte, uc) && uc == 0x01);
+        BOOST_TEST(test_attr("\x01\x02", word, us) && us ==  0x0102);
+        BOOST_TEST(test_attr("\x01\x02\x03\x04", dword, ui) && ui == 0x01020304);
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(test_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul) &&
+            ul == 0x0102030405060708LL);
+#endif
+#endif
+    }
+
+    {   // test native endian binaries
+#ifdef BOOST_LITTLE_ENDIAN
+        BOOST_TEST(test("\x01", byte(0x01)));
+        BOOST_TEST(test("\x01\x02", word(0x0201)));
+        BOOST_TEST(test("\x01\x02\x03\x04", dword(0x04030201)));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(test("\x01\x02\x03\x04\x05\x06\x07\x08",
+            qword(0x0807060504030201LL)));
+#endif
+#else
+        BOOST_TEST(test("\x01", 1, byte(0x01)));
+        BOOST_TEST(test("\x01\x02", 2, word(0x0102)));
+        BOOST_TEST(test("\x01\x02\x03\x04", 4, dword(0x01020304)));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(test("\x01\x02\x03\x04\x05\x06\x07\x08", 8,
+            qword(0x0102030405060708LL)));
+#endif
+#endif
+    }
+
+    {   // test big endian binaries
+        BOOST_TEST(test_attr("\x01\x02", big_word, us) && us == 0x0102);
+        BOOST_TEST(test_attr("\x01\x02\x03\x04", big_dword, ui) && ui == 0x01020304);
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(test_attr("\x01\x02\x03\x04\x05\x06\x07\x08", big_qword, ul)
+            && ul == 0x0102030405060708LL);
+#endif
+    }
+
+    {
+        BOOST_TEST(test("\x01\x02", big_word(0x0102)));
+        BOOST_TEST(test("\x01\x02\x03\x04", big_dword(0x01020304)));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(test("\x01\x02\x03\x04\x05\x06\x07\x08",
+            big_qword(0x0102030405060708LL)));
+#endif
+    }
+
+    {   // test little endian binaries
+        BOOST_TEST(test_attr("\x01\x02", little_word, us) && us == 0x0201);
+        BOOST_TEST(test_attr("\x01\x02\x03\x04", little_dword, ui) && ui == 0x04030201);
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(test_attr("\x01\x02\x03\x04\x05\x06\x07\x08", little_qword, ul)
+            && ul == 0x0807060504030201LL);
+#endif
+    }
+
+    {
+        BOOST_TEST(test("\x01\x02", little_word(0x0201)));
+        BOOST_TEST(test("\x01\x02\x03\x04", little_dword(0x04030201)));
+#ifdef BOOST_HAS_LONG_LONG
+        BOOST_TEST(test("\x01\x02\x03\x04\x05\x06\x07\x08",
+            little_qword(0x0807060504030201LL)));
+#endif
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/char.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/char.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,102 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit::qi;
+    using namespace boost::spirit::ascii;
+    using boost::spirit::char_;
+    using boost::spirit::wchar;
+
+    {
+        BOOST_TEST(test("x", 'x'));
+        BOOST_TEST(test(L"x", L'x'));
+
+        BOOST_TEST(test("x", char_));
+        BOOST_TEST(test("x", char_('x')));
+        BOOST_TEST(!test("x", char_('y')));
+        BOOST_TEST(test(L"x", char_(L'x')));
+        BOOST_TEST(!test(L"x", char_(L'y')));
+        BOOST_TEST(test("x", char_('a', 'z')));
+        BOOST_TEST(!test("x", char_('0', '9')));
+
+        BOOST_TEST(!test("x", ~char_));
+        BOOST_TEST(!test("x", ~char_('x')));
+        BOOST_TEST(test(" ", ~char_('x')));
+        BOOST_TEST(test("X", ~char_('x')));
+        BOOST_TEST(!test("x", ~char_('b', 'y')));
+        BOOST_TEST(test("a", ~char_('b', 'y')));
+        BOOST_TEST(test("z", ~char_('b', 'y')));
+
+        BOOST_TEST(test("x", ~~char_));
+        BOOST_TEST(test("x", ~~char_('x')));
+        BOOST_TEST(!test(" ", ~~char_('x')));
+        BOOST_TEST(!test("X", ~~char_('x')));
+        BOOST_TEST(test("x", ~~char_('b', 'y')));
+        BOOST_TEST(!test("a", ~~char_('b', 'y')));
+        BOOST_TEST(!test("z", ~~char_('b', 'y')));
+    }
+
+    {
+        BOOST_TEST(test("   x", 'x', space));
+        BOOST_TEST(test(L"   x", L'x', space));
+
+        BOOST_TEST(test("   x", char_, space));
+        BOOST_TEST(test("   x", char_('x'), space));
+        BOOST_TEST(!test("   x", char_('y'), space));
+        BOOST_TEST(test(L"   x", char_(L'x'), space));
+        BOOST_TEST(!test(L"   x", char_(L'y'), space));
+        BOOST_TEST(test("   x", char_('a', 'z'), space));
+        BOOST_TEST(!test("   x", char_('0', '9'), space));
+
+    }
+
+    {
+        BOOST_TEST(test(L"x", wchar));
+        BOOST_TEST(test(L"x", wchar(L'x')));
+        BOOST_TEST(!test(L"x", wchar(L'y')));
+        BOOST_TEST(test(L"x", wchar('a', 'z')));
+        BOOST_TEST(!test(L"x", wchar('0', '9')));
+
+        BOOST_TEST(!test(L"x", ~wchar));
+        BOOST_TEST(!test(L"x", ~wchar('x')));
+        BOOST_TEST(test(L" ", ~wchar('x')));
+        BOOST_TEST(test(L"X", ~wchar('x')));
+        BOOST_TEST(!test(L"x", ~wchar('b', 'y')));
+        BOOST_TEST(test(L"a", ~wchar('b', 'y')));
+        BOOST_TEST(test(L"z", ~wchar('b', 'y')));
+
+        BOOST_TEST(test(L"x", ~~wchar));
+        BOOST_TEST(test(L"x", ~~wchar('x')));
+        BOOST_TEST(!test(L" ", ~~wchar('x')));
+        BOOST_TEST(!test(L"X", ~~wchar('x')));
+        BOOST_TEST(test(L"x", ~~wchar('b', 'y')));
+        BOOST_TEST(!test(L"a", ~~wchar('b', 'y')));
+        BOOST_TEST(!test(L"z", ~~wchar('b', 'y')));
+    }
+
+    {   // lazy chars
+
+        using namespace boost::phoenix;
+        BOOST_TEST((test("x", char_(val('x')))));
+        BOOST_TEST((test("h", char_(val('a'), val('n')))));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/char_class.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/char_class.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,170 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2007 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/qi_domain.hpp>
+#include <boost/spirit/include/support_attribute_of.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using spirit_test::test_attr;
+
+    {
+        using namespace boost::spirit::ascii;
+        BOOST_TEST(test("1", alnum));
+        BOOST_TEST(!test(" ", alnum));
+        BOOST_TEST(!test("1", alpha));
+        BOOST_TEST(test("x", alpha));
+        BOOST_TEST(test(" ", blank));
+        BOOST_TEST(!test("x", blank));
+        BOOST_TEST(test("1", digit));
+        BOOST_TEST(!test("x", digit));
+        BOOST_TEST(test("a", lower));
+        BOOST_TEST(!test("A", lower));
+        BOOST_TEST(test("!", punct));
+        BOOST_TEST(!test("x", punct));
+        BOOST_TEST(test(" ", space));
+        BOOST_TEST(test("\n", space));
+        BOOST_TEST(test("\r", space));
+        BOOST_TEST(test("\t", space));
+        BOOST_TEST(test("A", upper));
+        BOOST_TEST(!test("a", upper));
+        BOOST_TEST(test("A", xdigit));
+        BOOST_TEST(test("0", xdigit));
+        BOOST_TEST(test("f", xdigit));
+        BOOST_TEST(!test("g", xdigit));
+    }
+
+    {
+        using namespace boost::spirit::iso8859_1;
+        BOOST_TEST(test("1", alnum));
+        BOOST_TEST(!test(" ", alnum));
+        BOOST_TEST(!test("1", alpha));
+        BOOST_TEST(test("x", alpha));
+        BOOST_TEST(test(" ", blank));
+        BOOST_TEST(!test("x", blank));
+        BOOST_TEST(test("1", digit));
+        BOOST_TEST(!test("x", digit));
+        BOOST_TEST(test("a", lower));
+        BOOST_TEST(!test("A", lower));
+        BOOST_TEST(test("!", punct));
+        BOOST_TEST(!test("x", punct));
+        BOOST_TEST(test(" ", space));
+        BOOST_TEST(test("\n", space));
+        BOOST_TEST(test("\r", space));
+        BOOST_TEST(test("\t", space));
+        BOOST_TEST(test("A", upper));
+        BOOST_TEST(!test("a", upper));
+        BOOST_TEST(test("A", xdigit));
+        BOOST_TEST(test("0", xdigit));
+        BOOST_TEST(test("f", xdigit));
+        BOOST_TEST(!test("g", xdigit));
+    }
+
+    {
+        using namespace boost::spirit::standard;
+        BOOST_TEST(test("1", alnum));
+        BOOST_TEST(!test(" ", alnum));
+        BOOST_TEST(!test("1", alpha));
+        BOOST_TEST(test("x", alpha));
+        BOOST_TEST(test(" ", blank));
+        BOOST_TEST(!test("x", blank));
+        BOOST_TEST(test("1", digit));
+        BOOST_TEST(!test("x", digit));
+        BOOST_TEST(test("a", lower));
+        BOOST_TEST(!test("A", lower));
+        BOOST_TEST(test("!", punct));
+        BOOST_TEST(!test("x", punct));
+        BOOST_TEST(test(" ", space));
+        BOOST_TEST(test("\n", space));
+        BOOST_TEST(test("\r", space));
+        BOOST_TEST(test("\t", space));
+        BOOST_TEST(test("A", upper));
+        BOOST_TEST(!test("a", upper));
+        BOOST_TEST(test("A", xdigit));
+        BOOST_TEST(test("0", xdigit));
+        BOOST_TEST(test("f", xdigit));
+        BOOST_TEST(!test("g", xdigit));
+    }
+
+    {
+        using namespace boost::spirit::standard_wide;
+        BOOST_TEST(test(L"1", alnum));
+        BOOST_TEST(!test(L" ", alnum));
+        BOOST_TEST(!test(L"1", alpha));
+        BOOST_TEST(test(L"x", alpha));
+        BOOST_TEST(test(L" ", blank));
+        BOOST_TEST(!test(L"x", blank));
+        BOOST_TEST(test(L"1", digit));
+        BOOST_TEST(!test(L"x", digit));
+        BOOST_TEST(test(L"a", lower));
+        BOOST_TEST(!test(L"A", lower));
+        BOOST_TEST(test(L"!", punct));
+        BOOST_TEST(!test(L"x", punct));
+        BOOST_TEST(test(L" ", space));
+        BOOST_TEST(test(L"\n", space));
+        BOOST_TEST(test(L"\r", space));
+        BOOST_TEST(test(L"\t", space));
+        BOOST_TEST(test(L"A", upper));
+        BOOST_TEST(!test(L"a", upper));
+        BOOST_TEST(test(L"A", xdigit));
+        BOOST_TEST(test(L"0", xdigit));
+        BOOST_TEST(test(L"f", xdigit));
+        BOOST_TEST(!test(L"g", xdigit));
+    }
+
+    {   // test attribute extraction
+        using boost::spirit::qi::domain;
+        using boost::spirit::traits::attribute_of;
+        using boost::spirit::iso8859_1::alpha;
+        using boost::spirit::iso8859_1::alpha_type;
+
+        BOOST_STATIC_ASSERT((
+            boost::is_same<
+                attribute_of<domain, alpha_type, char const*, int>::type
+              , char>::value));
+
+        int attr = 0;
+        BOOST_TEST(test_attr("a", alpha, attr));
+        BOOST_TEST(attr == 'a');
+    }
+
+    {   // test attribute extraction
+        using boost::spirit::iso8859_1::alpha;
+        using boost::spirit::iso8859_1::space;
+        char attr = 0;
+        BOOST_TEST(test_attr("     a", alpha, attr, space));
+        BOOST_TEST(attr == 'a');
+    }
+
+    {   // test action
+
+        using namespace boost::phoenix;
+        using namespace boost::spirit::ascii;
+        using boost::spirit::arg_names::_1;
+        char ch;
+
+        BOOST_TEST(test("x", alnum[ref(ch) = _1]));
+        BOOST_TEST(ch == 'x');
+        BOOST_TEST(test("   A", alnum[ref(ch) = _1], space));
+        BOOST_TEST(ch == 'A');
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/debug.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/debug.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,241 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+
+#define BOOST_SPIRIT_DEBUG
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/qi_debug.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit::qi;
+    using namespace boost::spirit::ascii;
+
+    { // basic tests
+        rule<char const*> a, b, c, start;
+
+        a = 'a';
+        b = 'b';
+        c = 'c';
+        BOOST_SPIRIT_DEBUG_NODE(a);
+        BOOST_SPIRIT_DEBUG_NODE(b);
+        BOOST_SPIRIT_DEBUG_NODE(c);
+
+        start = *(a | b | c);
+        BOOST_SPIRIT_DEBUG_NODE(start);
+        BOOST_TEST(test("abcabcacb", start));
+
+        start = (a | b) >> (start | b);
+        BOOST_SPIRIT_DEBUG_NODE(start);
+        BOOST_TEST(test("aaaabababaaabbb", start));
+        BOOST_TEST(test("aaaabababaaabba", start, false));
+    }
+
+    { // basic tests w/ skipper
+
+        rule<char const*, space_type> a, b, c, start;
+
+        a = 'a';
+        b = 'b';
+        c = 'c';
+        BOOST_SPIRIT_DEBUG_NODE(a);
+        BOOST_SPIRIT_DEBUG_NODE(b);
+        BOOST_SPIRIT_DEBUG_NODE(c);
+
+        start = *(a | b | c);
+        BOOST_TEST(test(" a b c a b c a c b", start, space));
+
+        // allow no skipping too:
+        BOOST_SPIRIT_DEBUG_NODE(start);
+        BOOST_TEST(test("abcabcacb", start));
+
+        start = (a | b) >> (start | b);
+        BOOST_SPIRIT_DEBUG_NODE(start);
+        BOOST_TEST(test(" a a a a b a b a b a a a b b b ", start, space));
+        BOOST_TEST(test(" a a a a b a b a b a a a b b a ", start, space, false));
+    }
+
+//     { // alias tests
+// 
+//         rule<char const*> a, b, c, d, start;
+// 
+//         a = 'a';
+//         b = 'b';
+//         c = 'c';
+//         d = start.alias(); // d will always track start
+// 
+//         start = *(a | b | c);
+//         BOOST_TEST(test("abcabcacb", d));
+// 
+//         start = (a | b) >> (start | b);
+//         BOOST_TEST(test("aaaabababaaabbb", d));
+//     }
+// 
+//     { // copy tests
+// 
+//         rule<char const*> a, b, c, start;
+// 
+//         a = 'a';
+//         b = 'b';
+//         c = 'c';
+// 
+//         // The FF is the dynamic equivalent of start = *(a | b | c);
+//         start = a;
+//         start = start.copy() | b;
+//         start = start.copy() | c;
+//         start = *(start.copy());
+// 
+//         BOOST_TEST(test("abcabcacb", start));
+// 
+//         // The FF is the dynamic equivalent of start = (a | b) >> (start | b);
+//         start = b;
+//         start = a | start.copy();
+//         start = start.copy() >> (start | b);
+// 
+//         BOOST_TEST(test("aaaabababaaabbb", start));
+//         BOOST_TEST(test("aaaabababaaabba", start, false));
+//     }
+// 
+//     { // context tests
+// 
+//         using namespace boost::phoenix;
+//         using namespace boost::spirit::ascii;
+//         using boost::spirit::arg_names::_1;
+//         using boost::spirit::arg_names::_val;
+// 
+//         char ch;
+//         rule<char const*, char()> a;
+//         a = alpha[_val = _1];
+// 
+//         BOOST_TEST(test("x", a[ref(ch) = _1]));
+//         BOOST_TEST(ch == 'x');
+// 
+//         BOOST_TEST(test_attr("z", a, ch)); // attribute is given.
+//         BOOST_TEST(ch == 'z');
+//     }
+// 
+//     { // context (w/arg) tests
+// 
+//         using namespace boost::phoenix;
+//         using namespace boost::spirit::ascii;
+//         using boost::spirit::arg_names::_1;
+//         using boost::spirit::arg_names::_r1;
+//         using boost::spirit::arg_names::_r2;
+//         using boost::spirit::arg_names::_val;
+// 
+//         char ch;
+//         rule<char const*, char(int)> a; // 1 arg
+//         a = alpha[_val = _1 + _r1];
+// 
+//         BOOST_TEST(test("x", a(val(1))[ref(ch) = _1]));
+//         BOOST_TEST(ch == 'x' + 1);
+// 
+//         BOOST_TEST(test_attr("a", a(1), ch)); // allow scalars as rule args too.
+//         BOOST_TEST(ch == 'a' + 1);
+// 
+//         rule<char const*, char(int, int)> b; // 2 args
+//         b = alpha[_val = _1 + _r1 + _r2];
+//         BOOST_TEST(test_attr("a", b(1, 2), ch));
+//         BOOST_TEST(ch == 'a' + 1 + 2);
+//     }
+// 
+//     { // context (w/locals) tests
+//         using namespace boost::phoenix;
+//         using namespace boost::spirit::ascii;
+//         using boost::spirit::arg_names::_1;
+//         using boost::spirit::arg_names::_a;
+//         using boost::spirit::char_;
+//         using boost::spirit::locals;
+// 
+//         rule<char const*, locals<char> > a; // 1 local
+//         a = alpha[_a = _1] >> char_(_a);
+//         BOOST_TEST(test("aa", a));
+//         BOOST_TEST(!test("ax", a));
+//     }
+// 
+//     { // context (w/args and locals) tests
+//         using namespace boost::phoenix;
+//         using namespace boost::spirit::ascii;
+//         using boost::spirit::arg_names::_1;
+//         using boost::spirit::arg_names::_r1;
+//         using boost::spirit::arg_names::_a;
+//         using boost::spirit::char_;
+//         using boost::spirit::locals;
+// 
+//         rule<char const*, void(int), locals<char> > a; // 1 arg + 1 local
+//         a = alpha[_a = _1 + _r1] >> char_(_a);
+//         BOOST_TEST(test("ab", a(val(1))));
+//         BOOST_TEST(test("xy", a(val(1))));
+//         BOOST_TEST(!test("ax", a(val(1))));
+//     }
+// 
+//     { // bug: test that injected attributes are ok
+//         using namespace boost::phoenix;
+//         using namespace boost::spirit::ascii;
+//         using boost::spirit::arg_names::_1;
+//         using boost::spirit::arg_names::_r1;
+//         using boost::spirit::arg_names::_val;
+//         using boost::spirit::char_;
+// 
+//         rule<char const*, char(int) > r;
+// 
+//         // problem code:
+//         r = char_(_r1)[_val = _1];
+//     }
+
+    { // error handling
+
+        using namespace boost::phoenix;
+        using namespace boost::spirit::ascii;
+        using boost::phoenix::val;
+        using boost::spirit::int_;
+        using boost::spirit::arg_names::_4; // what
+        using boost::spirit::arg_names::_3; // error pos
+        using boost::spirit::arg_names::_2; // end
+        using boost::spirit::qi::fail;
+
+        rule<char const*> r;
+        r = '(' > int_ > ',' > int_ > ')';
+
+        on_error<fail>
+        (
+            r, std::cout
+                << val("Error! Expecting: ")
+                << _4
+                << val(" Here: \"")
+                << construct<std::string>(_3, _2)
+                << val("\"")
+                << std::endl
+        );
+
+        BOOST_SPIRIT_DEBUG_NODE(r);
+        BOOST_TEST(test("(123,456)", r));
+        BOOST_TEST(!test("(abc,def)", r));
+        BOOST_TEST(!test("(123,456]", r));
+        BOOST_TEST(!test("(123;456)", r));
+        BOOST_TEST(!test("[123,456]", r));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/difference.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/difference.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,78 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+
+    {
+        BOOST_TEST(test("b", char_ - 'a'));
+        BOOST_TEST(!test("a", char_ - 'a'));
+        BOOST_TEST(test("/* abcdefghijk */", "/*" >> *(char_ - "*/") >> "*/"));
+    }
+
+    {
+        BOOST_TEST(test("b", char_ - no_case['a']));
+        BOOST_TEST(!test("a", char_ - no_case['a']));
+        BOOST_TEST(!test("A", char_ - no_case['a']));
+
+        BOOST_TEST(test("b", no_case[lower - 'a']));
+        BOOST_TEST(test("B", no_case[lower - 'a']));
+        BOOST_TEST(!test("a", no_case[lower - 'a']));
+        BOOST_TEST(!test("A", no_case[lower - 'a']));
+    }
+
+    {
+        // $$$ See difference.hpp why these tests are not done anymore. $$$
+
+        //~ BOOST_TEST(test("switcher", lit("switcher") - "switch"));
+        //~ BOOST_TEST(test("    switcher    ", lit("switcher") - "switch", space));
+
+        BOOST_TEST(!test("switch", lit("switch") - "switch"));
+    }
+
+    {
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+        std::string s;
+
+        BOOST_TEST(test(
+            "/*abcdefghijk*/"
+          , "/*" >> *(char_ - "*/")[ref(s) += _1] >> "*/"
+        ));
+        BOOST_TEST(s == "abcdefghijk");
+        s.clear();
+
+        BOOST_TEST(test(
+            "    /*abcdefghijk*/    "
+          , "/*" >> *(char_ - "*/")[ref(s) += _1] >> "*/"
+          , space
+        ));
+        BOOST_TEST(s == "abcdefghijk");
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/eps.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/eps.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,33 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_auxiliary.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST((test("", eps)));
+        BOOST_TEST((test("xxx", eps, false)));
+    }
+
+    {   // test action
+
+        using namespace boost::phoenix;
+        BOOST_TEST((test("", eps(val(true)))));
+        BOOST_TEST((!test("", eps(val(false)))));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/expect.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/expect.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,89 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+    using spirit_test::test;
+    using boost::spirit::qi::expectation_failure;
+
+    {
+        try
+        {
+            BOOST_TEST((test("aa", char_ > char_)));
+            BOOST_TEST((test("aaa", char_ > char_ > char_('a'))));
+            BOOST_TEST((test("xi", char_('x') > char_('i'))));
+            BOOST_TEST((!test("xi", char_('y') > char_('o')))); // should not throw!
+            BOOST_TEST((test("xin", char_('x') > char_('i') > char_('n'))));
+            BOOST_TEST((!test("xi", char_('x') > char_('o'))));
+        }
+        catch (expectation_failure<char const*> const& x)
+        {
+            std::cout << "expected: " << x.what << std::endl;
+            std::cout << "got: \"" << x.first << '"' << std::endl;
+
+            BOOST_TEST(x.what == "'o'");
+            BOOST_TEST(std::string(x.first, x.last) == "i");
+        }
+    }
+
+    {
+        try
+        {
+            BOOST_TEST((test(" a a ", char_ > char_, space)));
+            BOOST_TEST((test(" x i ", char_('x') > char_('i'), space)));
+            BOOST_TEST((!test(" x i ", char_('x') > char_('o'), space)));
+        }
+        catch (expectation_failure<char const*> const& x)
+        {
+            std::cout << "expected: " << x.what << std::endl;
+            std::cout << "got: \"" << x.first << '"' << std::endl;
+
+            BOOST_TEST(x.what == "'o'");
+            BOOST_TEST(std::string(x.first, x.last) == "i ");
+        }
+    }
+
+    {
+        try
+        {
+            BOOST_TEST((test("aA", no_case[char_('a') > 'a'])));
+            BOOST_TEST((test("BEGIN END", no_case[lit("begin") > "end"], space)));
+            BOOST_TEST((!test("BEGIN END", no_case[lit("begin") > "nend"], space)));
+        }
+        catch (expectation_failure<char const*> const& x)
+        {
+            std::cout << "expected: " << x.what << std::endl;
+            std::cout << "got: \"" << x.first << '"' << std::endl;
+
+            BOOST_TEST(x.what == "case-insensitive \"nend\"");
+            BOOST_TEST(std::string(x.first, x.last) == "END");
+        }
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/functor.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/functor.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,68 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2008 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 <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_auxiliary.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+struct number_parser : public boost::spirit::qi::functor_base
+{
+    template <typename Context, typename Iterator>
+    struct apply
+    {
+        typedef int type;
+    };
+
+    template <typename Attribute, typename Iterator, typename Context>
+    bool operator()(Attribute& attr, Context& ctx,
+        Iterator& first, Iterator const& last) const
+    {
+        if (first == last)
+            return false;
+
+        char ch = *first;
+        if (ch < '0' || ch > '9')
+            return false;
+
+        attr = 0;
+        do {
+            attr = attr * 10 + int(ch - '0');
+            ++first;
+        } while (first != last && (ch = *first, ch >= '0' && ch <= '9'));
+        return true;
+    }
+};
+
+boost::spirit::qi::functor_parser<number_parser> number;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+    using namespace boost::spirit::qi;
+
+    {
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+
+        int n = 0;
+        BOOST_TEST(test("1234", number));
+        BOOST_TEST(test("1234", number[ref(n) = _1]));
+        BOOST_TEST(n == 1234);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/grammar.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/grammar.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,109 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+using namespace boost::spirit::arg_names;
+
+struct num_list : grammar_def<char const*, space_type>
+{
+    num_list()
+    {
+        using boost::spirit::int_;
+        num = int_;
+        start = num >> *(',' >> num);
+    }
+
+    rule<char const*, space_type> start, num;
+};
+
+struct inh_g : grammar_def<char const*, int(int), space_type>
+{
+    inh_g()
+    {
+        start = lit("inherited")[_val = _r1];
+    }
+
+    rule<char const*, int(int), space_type> start, num;
+};
+
+struct my_skipper : grammar_def<char const*>
+{
+    my_skipper()
+    {
+        start = space;
+    }
+
+    rule<char const*> start, num;
+};
+
+struct num_list2 : grammar_def<char const*, grammar<my_skipper> >
+{
+    num_list2()
+    {
+        using boost::spirit::int_;
+        num = int_;
+        start = num >> *(',' >> num);
+    }
+
+    rule<char const*, grammar<my_skipper> > start, num;
+};
+
+int
+main()
+{
+    { // simple grammar test
+
+        num_list def;
+        grammar<num_list> nlist(def);
+        BOOST_TEST(test("123, 456, 789", nlist, space));
+    }
+
+    { // simple grammar test with user-skipper
+
+        num_list2 def;
+        grammar<num_list2> nlist(def);
+        my_skipper skipdef;
+        grammar<my_skipper> skip(skipdef);
+        BOOST_TEST(test("123, 456, 789", nlist, skip));
+    }
+
+    { // direct access to the rules
+
+        num_list def;
+        BOOST_TEST(test("123", def.num));
+        BOOST_TEST(test("123, 456, 789", def.start, space));
+    }
+
+    { // grammar with inherited attributes
+
+        inh_g def;
+        grammar<inh_g> g(def);
+        int n = -1;
+        BOOST_TEST(test_attr("inherited", def.start(123), n, space)); // direct to the rule
+        BOOST_TEST(n == 123);
+        BOOST_TEST(test_attr("inherited", g(123), n, space)); // using the grammar
+        BOOST_TEST(n == 123);
+    }
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/grammar_fail.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/grammar_fail.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,42 @@
+/*=============================================================================
+    Copyright (c) 2001-2008 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 <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+
+struct num_list : grammar_def<char const*, rule<char const*> >
+{
+    num_list()
+    {
+        using boost::spirit::int_;
+        num = int_;
+        start = num >> *(',' >> num);
+    }
+
+    rule<char const*, rule<char const*> > start, num;
+};
+
+// this test must fail compiling
+int main()
+{
+    char const* input = "some input, it doesn't matter";
+    char const* end = &input[strlen(input)+1];
+    
+    num_list def;
+    bool r = phrase_parse(input, end, make_parser(def),
+		    space | ('%' >> *~char_('\n') >> '\n'));
+
+    return 0;
+}
Added: trunk/libs/spirit/test/qi/int.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/int.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,164 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2008 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 <climits>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//  *** BEWARE PLATFORM DEPENDENT!!! ***
+//  *** The following assumes 32 bit integers and 64 bit long longs.
+//  *** Modify these constant strings when appropriate.
+//
+///////////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HAS_LONG_LONG
+// Some compilers have long long, but don't define the
+// LONG_LONG_MIN and LONG_LONG_MAX macros in limits.h.  This
+// assumes that long long is 64 bits.
+#if !defined(LONG_LONG_MIN) && !defined(LONG_LONG_MAX)
+# define LONG_LONG_MAX 0x7fffffffffffffffLL
+# define LONG_LONG_MIN (-LONG_LONG_MAX - 1)
+#endif
+#endif // BOOST_HAS_LONG_LONG
+
+    char const* max_int = "2147483647";
+    char const* int_overflow = "2147483648";
+    char const* min_int = "-2147483648";
+    char const* int_underflow = "-2147483649";
+
+#ifdef BOOST_HAS_LONG_LONG
+    char const* max_long_long = "9223372036854775807";
+    char const* long_long_overflow = "9223372036854775808";
+    char const* min_long_long = "-9223372036854775808";
+    char const* long_long_underflow = "-9223372036854775809";
+#endif
+
+int
+main()
+{
+    using namespace spirit_test;
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  signed integer tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::int_;
+        int i;
+
+        BOOST_TEST(test("123456", int_));
+        BOOST_TEST(test_attr("123456", int_, i));
+        BOOST_TEST(i == 123456);
+
+        BOOST_TEST(test("+123456", int_));
+        BOOST_TEST(test_attr("+123456", int_, i));
+        BOOST_TEST(i == 123456);
+
+        BOOST_TEST(test("-123456", int_));
+        BOOST_TEST(test_attr("-123456", int_, i));
+        BOOST_TEST(i == -123456);
+
+        BOOST_TEST(test(max_int, int_));
+        BOOST_TEST(test_attr(max_int, int_, i));
+        BOOST_TEST(i == INT_MAX);
+
+        BOOST_TEST(test(min_int, int_));
+        BOOST_TEST(test_attr(min_int, int_, i));
+        BOOST_TEST(i == INT_MIN);
+
+        BOOST_TEST(!test(int_overflow, int_));
+        BOOST_TEST(!test_attr(int_overflow, int_, i));
+        BOOST_TEST(!test(int_underflow, int_));
+        BOOST_TEST(!test_attr(int_underflow, int_, i));
+
+        BOOST_TEST(!test("-", int_));
+        BOOST_TEST(!test_attr("-", int_, i));
+
+        BOOST_TEST(!test("+", int_));
+        BOOST_TEST(!test_attr("+", int_, i));
+
+        // Bug report from Steve Nutt
+        BOOST_TEST(test_attr("5368709120", int_, i, false));
+        BOOST_TEST(i == 536870912);
+
+        // with leading zeros
+        BOOST_TEST(test("0000000000123456", int_));
+        BOOST_TEST(test_attr("0000000000123456", int_, i));
+        BOOST_TEST(i == 123456);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  long long tests
+    ///////////////////////////////////////////////////////////////////////////
+#ifdef BOOST_HAS_LONG_LONG
+    {
+        using boost::spirit::long_long;
+        boost::long_long_type ll;
+
+        BOOST_TEST(test("1234567890123456789", long_long));
+        BOOST_TEST(test_attr("1234567890123456789", long_long, ll));
+        BOOST_TEST(ll == 1234567890123456789LL);
+
+        BOOST_TEST(test("-1234567890123456789", long_long));
+        BOOST_TEST(test_attr("-1234567890123456789", long_long, ll));
+        BOOST_TEST(ll == -1234567890123456789LL);
+
+        BOOST_TEST(test(max_long_long, long_long));
+        BOOST_TEST(test_attr(max_long_long, long_long, ll));
+        BOOST_TEST(ll == LONG_LONG_MAX);
+
+        BOOST_TEST(test(min_long_long, long_long));
+        BOOST_TEST(test_attr(min_long_long, long_long, ll));
+        BOOST_TEST(ll == LONG_LONG_MIN);
+
+        BOOST_TEST(!test(long_long_overflow, long_long));
+        BOOST_TEST(!test_attr(long_long_overflow, long_long, ll));
+        BOOST_TEST(!test(long_long_underflow, long_long));
+        BOOST_TEST(!test_attr(long_long_underflow, long_long, ll));
+    }
+#endif
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  int_spec<unused_type> tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::qi::int_spec;
+        using boost::spirit::unused_type;
+        int_spec<unused_type> any_int;
+
+        BOOST_TEST(test("123456", any_int));
+        BOOST_TEST(test("-123456", any_int));
+        BOOST_TEST(test("-1234567890123456789", any_int));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  action tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+        using boost::spirit::ascii::space;
+        using boost::spirit::int_;
+        int n, m;
+
+        BOOST_TEST(test("123", int_[ref(n) = _1]));
+        BOOST_TEST(n == 123);
+        BOOST_TEST(test_attr("789", int_[ref(n) = _1], m));
+        BOOST_TEST(n == 789 && m == 789);
+        BOOST_TEST(test("   456", int_[ref(n) = _1], space));
+        BOOST_TEST(n == 456);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/kleene.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/kleene.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,113 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <string>
+#include <vector>
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+
+    {
+        BOOST_TEST(test("aaaaaaaa", *char_));
+        BOOST_TEST(test("a", *char_));
+        BOOST_TEST(test("", *char_));
+        BOOST_TEST(test("aaaaaaaa", *alpha));
+        BOOST_TEST(!test("aaaaaaaa", *upper));
+    }
+
+    {
+        BOOST_TEST(test(" a a aaa aa", *char_, space));
+        BOOST_TEST(test("12345 678 9 ", *digit, space));
+    }
+
+    {
+        BOOST_TEST(test("aBcdeFGH", no_case[*char_]));
+        BOOST_TEST(test("a B cde FGH  ", no_case[*char_], space));
+    }
+
+    {
+        using boost::spirit::uint;
+        BOOST_TEST(test("12345 678 955 987", *uint, space));
+        BOOST_TEST(test("12345, 678, 955, 987", uint >> *(',' >> uint), space));
+    }
+
+    {
+        std::vector<char> v;
+        BOOST_TEST(test_attr("bbbb", *char_, v) && 4 == v.size() &&
+            v[0] == 'b' && v[1] == 'b' && v[2] == 'b' &&  v[3] == 'b');
+
+        v.clear();
+        BOOST_TEST(test_attr("b b b b ", *char_, v, space) && 4 == v.size() &&
+            v[0] == 'b' && v[1] == 'b' && v[2] == 'b' && v[3] == 'b');
+
+        v.clear();
+        BOOST_TEST(test_attr("bbbb", *omit[char_('b')], v) && 0 == v.size());
+
+        v.clear();
+        BOOST_TEST(test_attr("bbbb", omit[*char_('b')], v) && 0 == v.size());
+
+        v.clear();
+        BOOST_TEST(test_attr("b b b b ", *omit[char_('b')], v, space) && 0 == v.size());
+
+        v.clear();
+        BOOST_TEST(test_attr("b b b b ", omit[*char_('b')], v, space) && 0 == v.size());
+    }
+
+    {
+        std::vector<int> v;
+        BOOST_TEST(test_attr("123 456 789 10", *int_, v, space) && 4 == v.size() &&
+            v[0] == 123 && v[1] == 456 && v[2] == 789 &&  v[3] == 10);
+    }
+
+    {
+        std::vector<int> v;
+        BOOST_TEST(test_attr("123 456 789", *int_, v, space) && 3 == v.size() &&
+            v[0] == 123 && v[1] == 456 && v[2] == 789);
+    }
+
+    { // actions
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+
+        std::vector<char> v;
+        BOOST_TEST(test("bbbb", (*char_)[ref(v) = _1]) && 4 == v.size() &&
+            v[0] == 'b' && v[1] == 'b' && v[2] == 'b' &&  v[3] == 'b');
+    }
+
+    { // more actions
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+
+        std::vector<int> v;
+        BOOST_TEST(test("123 456 789", (*int_)[ref(v) = _1], space) && 3 == v.size() &&
+            v[0] == 123 && v[1] == 456 && v[2] == 789);
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/lazy.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/lazy.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,54 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_auxiliary.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+    using namespace boost::spirit::qi;
+    using namespace boost::phoenix;
+    using namespace boost::spirit::arg_names;
+
+    {
+        BOOST_TEST(test("123", lazy(val(int_))));
+    }
+
+    {
+        int result;
+        BOOST_TEST(test("123", lazy(val(int_))[ref(result) = _1]));
+        BOOST_TEST((result == 123));
+    }
+
+    {
+        rule<char const*, std::string()> r;
+
+        r =
+                '<' >> *(char_ - '>')[_val += _1] >> '>'
+            >>  "</" >> lazy(_val) >> '>'
+        ;
+
+        BOOST_TEST(test("<tag></tag>", r));
+        BOOST_TEST(!test("<foo></bar>", r));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/lexeme.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/lexeme.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,38 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+    using boost::spirit::qi::rule;
+
+    {
+        BOOST_TEST((test(" 1 2 3 4 5", +digit, space)));
+        BOOST_TEST((!test(" 1 2 3 4 5", lexeme[+digit], space)));
+        BOOST_TEST((test(" 12345", lexeme[+digit], space)));
+        BOOST_TEST((test(" 12345  ", lexeme[+digit], space, false)));
+
+        rule<char const*, space_type> r, rr;
+        r = +digit;
+        rr = lexeme[r];
+        BOOST_TEST((!test(" 1 2 3 4 5", rr, space)));
+        BOOST_TEST((test(" 12345", rr, space)));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/list.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/list.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,64 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <string>
+#include <vector>
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+
+    {
+        BOOST_TEST(test("a,b,c,d,e,f,g,h", char_ % ','));
+        BOOST_TEST(test("a,b,c,d,e,f,g,h,", char_ % ',', false));
+    }
+
+    {
+        BOOST_TEST(test("a, b, c, d, e, f, g, h", char_ % ',', space));
+        BOOST_TEST(test("a, b, c, d, e, f, g, h,", char_ % ',', space, false));
+    }
+
+    {
+        std::string s;
+        BOOST_TEST(test_attr("a,b,c,d,e,f,g,h", char_ % ',', s));
+        BOOST_TEST(s == "abcdefgh");
+    }
+
+    { // actions
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+
+        std::string s;
+        BOOST_TEST(test("a,b,c,d,e,f,g,h", (char_ % ',')
+            [ref(s) = construct<std::string>(begin(_1), end(_1))]));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/lit.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/lit.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,79 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using spirit_test::test_attr;
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST((test("kimpo", "kimpo")));
+        BOOST_TEST((test("kimpo", lit("kimpo"))));
+        BOOST_TEST((test("x", lit("x"))));
+        BOOST_TEST((test("x", lit('x'))));
+        BOOST_TEST((test(L"x", lit(L'x'))));
+    }
+
+    {
+        BOOST_TEST((test(L"kimpo", L"kimpo")));
+        BOOST_TEST((test(L"kimpo", wlit(L"kimpo"))));
+        BOOST_TEST((test(L"x", wlit(L"x"))));
+        BOOST_TEST((test(L"x", wlit(L'x'))));
+        BOOST_TEST((test(L"x", wlit(L'x'))));
+    }
+
+    {
+        std::basic_string<char> s("kimpo");
+        BOOST_TEST((test("kimpo", lit(s))));
+
+        std::basic_string<wchar_t> ws(L"kimpo");
+        BOOST_TEST((test(L"kimpo", lit(ws))));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        BOOST_TEST((test("    kimpo", lit("kimpo"), space)));
+        BOOST_TEST((test(L"    kimpo", lit(L"kimpo"), space)));
+        BOOST_TEST((test("    x", lit("x"), space)));
+        BOOST_TEST((test("    x", lit('x'), space)));
+        BOOST_TEST((test(L"    x", lit(L'x'), space)));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        BOOST_TEST((test("    kimpo", wlit("kimpo"), space)));
+        BOOST_TEST((test(L"    kimpo", wlit(L"kimpo"), space)));
+        BOOST_TEST((test("    x", wlit("x"), space)));
+        BOOST_TEST((test("    x", wlit('x'), space)));
+        BOOST_TEST((test(L"    x", wlit(L'x'), space)));
+    }
+
+    {   // lazy strings
+
+        using namespace boost::phoenix;
+        std::basic_string<char> s("kimpo");
+        BOOST_TEST((test("kimpo", lit(val(s)))));
+
+        std::basic_string<wchar_t> ws(L"kimpo");
+        BOOST_TEST((test(L"kimpo", lit(ref(ws)))));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/match_manip.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/match_manip.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,293 @@
+//  Copyright (c) 2001-2008 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 <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/qi_stream.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <list>
+
+#include <boost/static_assert.hpp>
+#include <boost/detail/lightweight_test.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename Char, typename Expr>
+bool test(Char const *toparse, Expr const& xpr)
+{
+    namespace spirit = boost::spirit;
+    typedef
+        spirit::traits::is_component<spirit::qi::domain, Expr>
+    is_component;
+
+    // report invalid expression error as early as possible
+    BOOST_MPL_ASSERT_MSG(is_component::value,
+        xpr_is_not_convertible_to_a_parser, ());
+
+    typedef
+        typename spirit::result_of::as_component<spirit::qi::domain, Expr>::type
+    component;
+    typedef typename component::director director;
+
+    component c = spirit::as_component(spirit::qi::domain(), xpr);
+
+    std::istringstream istrm(toparse);
+    istrm >> c;
+    return istrm.good() || istrm.eof();
+}
+
+template <typename Char, typename Expr, typename Attribute, typename Skipper>
+bool test(Char const *toparse,
+    boost::spirit::qi::detail::match_manip<Expr, Attribute, Skipper> const& mm)
+{
+    std::istringstream istrm(toparse);
+    istrm >> mm;
+    return istrm.good() || istrm.eof();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool is_list_ok(std::list<char> const& l)
+{
+    std::list<char>::const_iterator cit = l.begin();
+    if (cit == l.end() || *cit != 'a')
+        return false;
+    if (++cit == l.end() || *cit != 'b')
+        return false;
+
+    return ++cit != l.end() && *cit == 'c';
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+    using namespace boost::spirit::arg_names;
+    using namespace boost::spirit::qi;
+
+    namespace fusion = boost::fusion;
+    using namespace boost::phoenix;
+
+    {
+        char c = '\0';
+        BOOST_TEST(test( "a",
+            char_[ref(c) = _1]
+        ) && c == 'a');
+
+        c = '\0';
+        BOOST_TEST(test( "a",
+            match(char_[ref(c) = _1])
+        ) && c == 'a');
+
+        c = '\0';
+        BOOST_TEST(test( " a",
+            phrase_match(char_[ref(c) = _1], space)
+        ) && c == 'a');
+
+        c = '\0';
+        BOOST_TEST(test( "a",
+            match(char_, c)
+        ) && c == 'a');
+
+        c = '\0';
+        BOOST_TEST(test( " a",
+            phrase_match(char_, c, space)
+        ) && c == 'a');
+    }
+
+    {
+        ///////////////////////////////////////////////////////////////////////
+        typedef typed_stream<char> char_stream_type;
+        char_stream_type const char_stream = char_stream_type();
+
+        typedef typed_stream<int> int_stream_type;
+        int_stream_type const int_stream = int_stream_type();
+
+        ///////////////////////////////////////////////////////////////////////
+        char c = '\0';
+        BOOST_TEST(test( "a",
+            char_stream[ref(c) = _1]
+        ) && c == 'a');
+
+        c = '\0';
+        BOOST_TEST(test( "a",
+            match(char_stream[ref(c) = _1])
+        ) && c == 'a');
+
+        c = '\0';
+        BOOST_TEST(test( " a",
+            phrase_match(char_stream[ref(c) = _1], space)
+        ) && c == 'a');
+
+        int i = 0;
+        BOOST_TEST(test( "42",
+            int_stream[ref(i) = _1]
+        ) && i == 42);
+
+        i = 0;
+        BOOST_TEST(test( "42",
+            match(int_stream[ref(i) = _1])
+        ) && i == 42);
+
+        i = 0;
+        BOOST_TEST(test( " 42",
+            phrase_match(int_stream[ref(i) = _1], space)
+        ) && i == 42);
+
+        ///////////////////////////////////////////////////////////////////////
+        c = '\0';
+        BOOST_TEST(test( "a",
+            match(stream, c)
+        ) && c == 'a');
+
+        c = '\0';
+        BOOST_TEST(test( " a",
+            phrase_match(stream, c, space)
+        ) && c == 'a');
+
+        i = 0;
+        BOOST_TEST(test( "42",
+            match(stream, i)
+        ) && i == 42);
+
+        i = 0;
+        BOOST_TEST(test( " 42",
+            phrase_match(stream, i, space)
+        ) && i == 42);
+    }
+
+    {
+        char a = '\0', b = '\0';
+        BOOST_TEST(test( "ab",
+            char_[ref(a) = _1] >> char_[ref(b) = _1]
+        ) && a == 'a' && b == 'b');
+
+        a = '\0', b = '\0';
+        BOOST_TEST(test( "ab",
+            match(char_[ref(a) = _1] >> char_[ref(b) = _1])
+        ) && a == 'a' && b == 'b');
+
+        a = '\0', b = '\0';
+        BOOST_TEST(test( " a b",
+            phrase_match(char_[ref(a) = _1] >> char_[ref(b) = _1], space)
+        ) && a == 'a' && b == 'b');
+
+        fusion::vector<char, char> t;
+        BOOST_TEST(test( "ab",
+            match(char_ >> char_, t)
+        ) && fusion::at_c<0>(t) == 'a' && fusion::at_c<1>(t) == 'b');
+
+        t = fusion::vector<char, char>();
+        BOOST_TEST(test( " a b",
+            phrase_match(char_ >> char_, t, space)
+        ) && fusion::at_c<0>(t) == 'a' && fusion::at_c<1>(t) == 'b');
+    }
+
+    {
+        char a = '\0', b = '\0', c = '\0';
+        BOOST_TEST(test( "abc",
+            char_[ref(a) = _1] >> char_[ref(b) = _1] >> char_[ref(c) = _1]
+        ) && a == 'a' && b == 'b' && c == 'c');
+
+        BOOST_TEST(test( "abc",
+            match(char_('a') >> char_('b') >> char_('c'))
+        ));
+
+        BOOST_TEST(test( " a b c",
+            phrase_match(char_('a') >> char_('b') >> char_('c'), space)
+        ));
+
+        BOOST_TEST(!test( "abc",
+            match(char_('a') >> char_('b') >> char_('d'))
+        ));
+
+        BOOST_TEST(!test( " a b c",
+            phrase_match(char_('a') >> char_('b') >> char_('d'), space)
+        ));
+
+        fusion::vector<char, char, char> t;
+        BOOST_TEST(test( "abc",
+            match(char_ >> char_ >> char_, t)
+        ) && fusion::at_c<0>(t) == 'a' && fusion::at_c<1>(t) == 'b' && fusion::at_c<2>(t) == 'c');
+
+        t = fusion::vector<char, char, char>();
+        BOOST_TEST(test( " a b c",
+            phrase_match(char_ >> char_ >> char_, t, space)
+        ) && fusion::at_c<0>(t) == 'a' && fusion::at_c<1>(t) == 'b' && fusion::at_c<2>(t) == 'c');
+    }
+
+    {
+        char a = '\0';
+        int i = 0;
+        BOOST_TEST(test( "a2",
+            (char_ >> int_)[ref(a) = _1, ref(i) = _2]
+        ) && a == 'a' && i == 2);
+
+        fusion::vector<char, int> t;
+        BOOST_TEST(test( "a2",
+            match(char_ >> int_, t)
+        ) && fusion::at_c<0>(t) == 'a' && fusion::at_c<1>(t) == 2);
+
+        t = fusion::vector<char, int>();
+        BOOST_TEST(test( " a 2",
+            phrase_match(char_ >> int_, t, space)
+        ) && fusion::at_c<0>(t) == 'a' && fusion::at_c<1>(t) == 2);
+
+        BOOST_TEST(!test( "a2",
+            match(char_ >> alpha, t)
+        ));
+        BOOST_TEST(!test( " a 2",
+            phrase_match(char_ >> alpha, t, space)
+        ));
+    }
+
+    {
+        // output all elements of a vector
+        std::vector<char> v;
+        BOOST_TEST(test( "abc",
+            (*char_)[ref(v) = _1]
+        ) && 3 == v.size() && v[0] == 'a' && v[1] == 'b' && v[2] == 'c');
+
+        v.clear();
+        BOOST_TEST(test( "abc",
+            match(*char_, v)
+        ) && 3 == v.size() && v[0] == 'a' && v[1] == 'b' && v[2] == 'c');
+
+        v.clear();
+        BOOST_TEST(test( " a b c",
+            phrase_match(*char_, v, space)
+        ) && 3 == v.size() && v[0] == 'a' && v[1] == 'b' && v[2] == 'c');
+
+        // parse a comma separated list of vector elements
+        v.clear();
+        BOOST_TEST(test( "a,b,c",
+            match(char_ % ',', v)
+        ) && 3 == v.size() && v[0] == 'a' && v[1] == 'b' && v[2] == 'c');
+
+        v.clear();
+        BOOST_TEST(test( " a , b , c",
+            phrase_match(char_ % ',', v, space)
+        ) && 3 == v.size() && v[0] == 'a' && v[1] == 'b' && v[2] == 'c');
+
+        // output all elements of a list
+        std::list<char> l;
+        BOOST_TEST(test( "abc",
+            match(*char_, l)
+        ) && 3 == l.size() && is_list_ok(l));
+
+        l.clear();
+        BOOST_TEST(test( " a b c",
+            phrase_match(*char_, l, space)
+        ) && 3 == l.size() && is_list_ok(l));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/no_case.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/no_case.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,95 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+
+    {
+        using namespace boost::spirit::ascii;
+        BOOST_TEST(test("x", no_case[char_]));
+        BOOST_TEST(test("X", no_case[char_('x')]));
+        BOOST_TEST(test("X", no_case[char_('X')]));
+        BOOST_TEST(test("x", no_case[char_('X')]));
+        BOOST_TEST(test("x", no_case[char_('x')]));
+        BOOST_TEST(!test("z", no_case[char_('X')]));
+        BOOST_TEST(!test("z", no_case[char_('x')]));
+        BOOST_TEST(test("x", no_case[char_('a', 'z')]));
+        BOOST_TEST(test("X", no_case[char_('a', 'z')]));
+        BOOST_TEST(!test("a", no_case[char_('b', 'z')]));
+        BOOST_TEST(!test("z", no_case[char_('a', 'y')]));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        BOOST_TEST(test("Bochi Bochi", no_case[lit("bochi bochi")]));
+        BOOST_TEST(test("BOCHI BOCHI", no_case[lit("bochi bochi")]));
+        BOOST_TEST(!test("Vavoo", no_case[lit("bochi bochi")]));
+    }
+
+    {
+        // should work!
+        using namespace boost::spirit::ascii;
+        BOOST_TEST(test("x", no_case[no_case[char_]]));
+        BOOST_TEST(test("x", no_case[no_case[char_('x')]]));
+        BOOST_TEST(test("yabadabadoo", no_case[no_case[lit("Yabadabadoo")]]));
+    }
+
+    {
+        using namespace boost::spirit::ascii;
+        BOOST_TEST(test("X", no_case[alnum]));
+        BOOST_TEST(test("6", no_case[alnum]));
+        BOOST_TEST(!test(":", no_case[alnum]));
+
+        BOOST_TEST(test("X", no_case[lower]));
+        BOOST_TEST(test("x", no_case[lower]));
+        BOOST_TEST(test("X", no_case[upper]));
+        BOOST_TEST(test("x", no_case[upper]));
+        BOOST_TEST(!test(":", no_case[lower]));
+        BOOST_TEST(!test(":", no_case[upper]));
+    }
+
+    {
+        using namespace boost::spirit::iso8859_1;
+        BOOST_TEST(test("X", no_case[alnum]));
+        BOOST_TEST(test("6", no_case[alnum]));
+        BOOST_TEST(!test(":", no_case[alnum]));
+
+        BOOST_TEST(test("X", no_case[lower]));
+        BOOST_TEST(test("x", no_case[lower]));
+        BOOST_TEST(test("X", no_case[upper]));
+        BOOST_TEST(test("x", no_case[upper]));
+        BOOST_TEST(!test(":", no_case[lower]));
+        BOOST_TEST(!test(":", no_case[upper]));
+    }
+
+    {
+        using namespace boost::spirit::standard;
+        BOOST_TEST(test("X", no_case[alnum]));
+        BOOST_TEST(test("6", no_case[alnum]));
+        BOOST_TEST(!test(":", no_case[alnum]));
+
+        BOOST_TEST(test("X", no_case[lower]));
+        BOOST_TEST(test("x", no_case[lower]));
+        BOOST_TEST(test("X", no_case[upper]));
+        BOOST_TEST(test("x", no_case[upper]));
+        BOOST_TEST(!test(":", no_case[lower]));
+        BOOST_TEST(!test(":", no_case[upper]));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/none.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/none.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,25 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_auxiliary.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST((!test("", none)));
+        BOOST_TEST((!test("xxx", none)));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/not_predicate.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/not_predicate.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,27 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST((!test("1234", !int_)));
+        BOOST_TEST((test("abcd", !int_, false)));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/optional.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/optional.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,66 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using spirit_test::test_attr;
+    using namespace boost::spirit;
+
+    {
+        BOOST_TEST((test("1234", -int_)));
+        BOOST_TEST((test("abcd", -int_, false)));
+    }
+
+    {   // test propagation of unused
+        using namespace boost::fusion;
+
+        vector<char, char> v;
+        BOOST_TEST((test_attr("a1234c", char_ >> -omit[int_] >> char_, v)));
+        BOOST_TEST((at_c<0>(v) == 'a'));
+        BOOST_TEST((at_c<1>(v) == 'c'));
+
+        v = boost::fusion::vector<char, char>();
+        BOOST_TEST((test_attr("a1234c", char_ >> omit[-int_] >> char_, v)));
+        BOOST_TEST((at_c<0>(v) == 'a'));
+        BOOST_TEST((at_c<1>(v) == 'c'));
+
+        //~ char ch;
+        //~ BOOST_TEST((test_attr(",c", -(',' >> char_), ch)));
+        //~ BOOST_TEST((ch == 'c'));
+    }
+
+    {   // test action
+
+        using namespace boost::phoenix;
+        namespace phx = boost::phoenix;
+        using namespace boost::spirit::arg_names;
+
+        boost::optional<int> n = 0;
+        BOOST_TEST((test("1234", (-int_)[phx::ref(n) = _1])));
+        BOOST_TEST(n.get() == 1234);
+
+        n = boost::optional<int>();
+        BOOST_TEST((test("abcd", (-int_)[phx::ref(n) = _1], false)));
+        BOOST_TEST(!n);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/permutation.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/permutation.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,121 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/optional.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using boost::spirit::ascii::alpha;
+    using boost::spirit::qi::rule;
+    using boost::fusion::vector;
+    using boost::fusion::at_c;
+    using boost::optional;
+
+    {
+        BOOST_TEST((test("a", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("b", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("ab", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("ba", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("abc", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("acb", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("bca", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("bac", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("cab", char_('a') ^ char_('b') ^ char_('c'))));
+        BOOST_TEST((test("cba", char_('a') ^ char_('b') ^ char_('c'))));
+
+        BOOST_TEST((!test("cca", char_('a') ^ char_('b') ^ char_('c'))));
+    }
+
+    {
+        vector<optional<int>, optional<char> > attr;
+
+        BOOST_TEST((test_attr("a", int_ ^ alpha, attr)));
+        BOOST_TEST((!at_c<0>(attr)));
+        BOOST_TEST((at_c<1>(attr).get() == 'a'));
+
+        at_c<1>(attr) = optional<char>(); // clear the optional
+        BOOST_TEST((test_attr("123", int_ ^ alpha, attr)));
+        BOOST_TEST((at_c<0>(attr).get() == 123));
+        BOOST_TEST((!at_c<1>(attr)));
+
+        at_c<0>(attr) = optional<int>(); // clear the optional
+        BOOST_TEST((test_attr("123a", int_ ^ alpha, attr)));
+        BOOST_TEST((at_c<0>(attr).get() == 123));
+        BOOST_TEST((at_c<1>(attr).get() == 'a'));
+
+        at_c<0>(attr) = optional<int>(); // clear the optional
+        at_c<1>(attr) = optional<char>(); // clear the optional
+        BOOST_TEST((test_attr("a123", int_ ^ alpha, attr)));
+        BOOST_TEST((at_c<0>(attr).get() == 123));
+        BOOST_TEST((at_c<1>(attr).get() == 'a'));
+    }
+
+    {   // test action
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        namespace phx = boost::phoenix;
+
+        optional<int> i;
+        optional<char> c;
+
+        BOOST_TEST((test("123a", (int_ ^ alpha)[phx::ref(i) = _1, phx::ref(c) = _2])));
+        BOOST_TEST((i.get() == 123));
+        BOOST_TEST((c.get() == 'a'));
+    }
+
+    {   // test rule %=
+
+        typedef vector<optional<int>, optional<char> > attr_type;
+        attr_type attr;
+
+        rule<char const*, attr_type()> r;
+        r %= int_ ^ alpha;
+
+        BOOST_TEST((test_attr("a", r, attr)));
+        BOOST_TEST((!at_c<0>(attr)));
+        BOOST_TEST((at_c<1>(attr).get() == 'a'));
+
+        at_c<1>(attr) = optional<char>(); // clear the optional
+        BOOST_TEST((test_attr("123", r, attr)));
+        BOOST_TEST((at_c<0>(attr).get() == 123));
+        BOOST_TEST((!at_c<1>(attr)));
+
+        at_c<0>(attr) = optional<int>(); // clear the optional
+        BOOST_TEST((test_attr("123a", r, attr)));
+        BOOST_TEST((at_c<0>(attr).get() == 123));
+        BOOST_TEST((at_c<1>(attr).get() == 'a'));
+
+        at_c<0>(attr) = optional<int>(); // clear the optional
+        at_c<1>(attr) = optional<char>(); // clear the optional
+        BOOST_TEST((test_attr("a123", r, attr)));
+        BOOST_TEST((at_c<0>(attr).get() == 123));
+        BOOST_TEST((at_c<1>(attr).get() == 'a'));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/plus.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/plus.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,98 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <string>
+#include <vector>
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+
+    {
+        BOOST_TEST(test("aaaaaaaa", +char_));
+        BOOST_TEST(test("a", +char_));
+        BOOST_TEST(!test("", +char_));
+        BOOST_TEST(test("aaaaaaaa", +alpha));
+        BOOST_TEST(!test("aaaaaaaa", +upper));
+    }
+
+    {
+        BOOST_TEST(test(" a a aaa aa", +char_, space));
+        BOOST_TEST(test("12345 678 9 ", +digit, space));
+    }
+
+    {
+        BOOST_TEST(test("aBcdeFGH", no_case[+char_]));
+        BOOST_TEST(test("a B cde FGH  ", no_case[+char_], space));
+    }
+
+    {
+        std::vector<int> v;
+        BOOST_TEST(test_attr("123 456 789 10", +int_, v, space) && 4 == v.size() &&
+            v[0] == 123 && v[1] == 456 && v[2] == 789 &&  v[3] == 10);
+    }
+
+    {
+        BOOST_TEST(test("Kim Kim Kim", +lit("Kim"), space));
+    }
+
+    {
+        std::vector<char> v;
+        v.clear();
+        BOOST_TEST(test_attr("bbbb", +omit[char_('b')], v) && 0 == v.size());
+
+        v.clear();
+        BOOST_TEST(test_attr("bbbb", omit[+char_('b')], v) && 0 == v.size());
+
+        v.clear();
+        BOOST_TEST(test_attr("b b b b ", +omit[char_('b')], v, space) && 0 == v.size());
+
+        v.clear();
+        BOOST_TEST(test_attr("b b b b ", omit[+char_('b')], v, space) && 0 == v.size());
+    }
+
+    { // actions
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+
+        std::vector<char> v;
+        BOOST_TEST(test("bbbb", (+char_)[ref(v) = _1]) && 4 == v.size() &&
+            v[0] == 'b' && v[1] == 'b' && v[2] == 'b' &&  v[3] == 'b');
+    }
+
+    { // more actions
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+
+        std::vector<int> v;
+        BOOST_TEST(test("1 2 3", (+int_)[ref(v) = _1], space) && 3 == v.size() &&
+            v[0] == 1 && v[1] == 2 && v[2] == 3);
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/range_run.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/range_run.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,167 @@
+/*=============================================================================
+    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)
+==============================================================================*/
+#include <iostream>
+#include <cctype>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/qi/char/detail/range_run.hpp>
+#include <boost/random.hpp>
+#include <boost/dynamic_bitset.hpp>
+#include <boost/integer_traits.hpp>
+
+#if defined(BOOST_MSVC)
+# pragma warning(disable: 4800) // 'int' : forcing value to bool 'true' or 'false' warning
+#endif
+
+template <typename Char>
+void acid_test()
+{
+    using boost::spirit::qi::detail::range_run;
+    using boost::spirit::qi::detail::range;
+
+    typedef boost::integer_traits<Char> integer_traits;
+    Char const const_min = integer_traits::const_min;
+    Char const const_max = integer_traits::const_max;
+    int const test_size = 1000;
+
+    boost::mt19937 rng;
+    boost::uniform_int<> char_(const_min, const_max);
+    boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
+       gen(rng, char_);
+    boost::uniform_int<> _1of10(1, 10);
+    boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
+       on_or_off(rng, _1of10);
+
+    range_run<Char> rr;
+    boost::dynamic_bitset<> bset(const_max-const_min+1);
+
+    for (int i = 0; i < test_size; ++i)
+    {
+        range<Char> r = range<Char>(gen(), gen());
+        if (r.first > r.last)
+            std::swap(r.first, r.last);
+
+        bool set = on_or_off() != 1;
+        if (set)
+            rr.set(r);
+        else
+            rr.clear(r);
+        for (int j = r.first; j <= int(r.last); ++j)
+            bset[j-const_min] = set;
+    }
+
+    for (int i = const_min; i <= int(const_max); ++i)
+    {
+        BOOST_TEST(rr.test(i) == bset[i-const_min]);
+    }
+}
+
+int
+main()
+{
+    using boost::spirit::qi::detail::range_run;
+    using boost::spirit::qi::detail::range;
+
+    {
+        range_run<char> rr;
+        rr.set(range<char>('a', 'a'));
+        for (char c = 0; c < 127; ++c)
+        {
+            BOOST_TEST(c == 'a' == rr.test(c));
+        }
+    }
+    {
+        range_run<char> rr;
+        rr.set(range<char>('a', 'z'));
+        rr.set(range<char>('A', 'Z'));
+        rr.clear(range<char>('A', 'Z'));
+        for (char c = 0; c < 127; ++c)
+        {
+            BOOST_TEST(bool(std::islower(c)) == rr.test(c));
+        }
+    }
+    {
+        range_run<char> rr;
+        rr.set(range<char>(0, 0));
+        for (char c = 0; c < 127; ++c)
+        {
+            BOOST_TEST(c == 0 == rr.test(c));
+        }
+        rr.set(range<char>(0, 50));
+        for (char c = 0; c < 127; ++c)
+        {
+            BOOST_TEST(((c >= 0) && (c <= 50)) == rr.test(c));
+        }
+    }
+    {
+        range_run<unsigned char> rr;
+        rr.set(range<unsigned char>(255, 255));
+        for (unsigned char c = 0; c < 255; ++c)
+        {
+            BOOST_TEST(c == 255 == rr.test(c));
+        }
+        rr.set(range<unsigned char>(250, 255));
+        for (unsigned char c = 0; c < 255; ++c)
+        {
+            BOOST_TEST((c >= 250) == rr.test(c));
+        }
+    }
+    {
+        range_run<char> rr;
+        rr.set(range<char>('a', 'z'));
+        rr.set(range<char>('A', 'Z'));
+        for (char c = 0; c < 127; ++c)
+        {
+            BOOST_TEST(bool(std::isalpha(c)) == rr.test(c));
+        }
+    }
+    {
+        range_run<char> rr;
+        rr.set(range<char>('a', 'z'));
+        rr.set(range<char>('A', 'Z'));
+        rr.clear(range<char>('J', 'j'));
+        for (char c = 0; c < 127; ++c)
+        {
+            BOOST_TEST((bool(std::isalpha(c)) && (c < 'J' || c > 'j')) == rr.test(c));
+        }
+    }
+    {
+        range_run<char> rr;
+        rr.set(range<char>(3, 3));
+        rr.set(range<char>(1, 5));
+        BOOST_TEST(rr.test(5));
+    }
+    {
+        range_run<char> rr;
+        for (char c = 0; c < 127; ++c)
+        {
+            if (c & 1)
+            {
+                rr.set(range<char>(c, c));
+            }
+        }
+        for (char c = 0; c < 127; ++c)
+        {
+            BOOST_TEST(bool((c & 1)) == rr.test(c));
+        }
+        rr.clear(range<char>(90, 105));
+        for (char c = 0; c < 127; ++c)
+        {
+            BOOST_TEST((bool((c & 1)) && (c < 90 || c > 105)) == rr.test(c));
+        }
+    }
+    {
+        acid_test<char>();
+        acid_test<signed char>();
+        acid_test<unsigned char>();
+        acid_test<wchar_t>();
+        acid_test<short>();
+        acid_test<signed short>();
+        acid_test<unsigned short>();
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/raw.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/raw.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,39 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+
+#include <iostream>
+#include <string>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test_attr;
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+    using boost::spirit::qi::rule;
+
+    {
+        boost::iterator_range<char const*> range;
+        std::string str;
+        BOOST_TEST((test_attr("spirit_test_123", raw[alpha >> *(alnum | '_')], range)));
+        BOOST_TEST((std::string(range.begin(), range.end()) == "spirit_test_123"));
+    }
+
+    {
+        std::string str;
+        BOOST_TEST((test_attr("spirit_test_123", raw[alpha >> *(alnum | '_')], str)));
+        BOOST_TEST((str == "spirit_test_123"));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/real.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/real.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,374 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2008 Hartmut Kaiser
+
+    Use, modification and distribution is subject to the Boost Software
+    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+    http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <climits>
+#include <boost/math/concepts/real_concept.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/support/detail/math/fpclassify.hpp>
+#include <boost/spirit/support/detail/math/signbit.hpp>
+
+#include "test.hpp"
+using namespace spirit_test;
+
+///////////////////////////////////////////////////////////////////////////////
+//  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)
+    {
+        return boost::spirit::qi::
+            extract_uint<T, 10, 1, 2, true>::call(first, last, attr);
+    }
+
+    //  No exponent
+    template <typename Iterator>
+    static bool
+    parse_exp(Iterator& first, Iterator const& last)
+    {
+        return false;
+    }
+
+    //  No exponent
+    template <typename Iterator, typename Attribute>
+    static bool
+    parse_exp_n(Iterator& first, Iterator const& last, Attribute& attr)
+    {
+        return false;
+    }
+
+    //  Thousands separated numbers
+    template <typename Iterator, typename Attribute>
+    static bool
+    parse_n(Iterator& first, Iterator const& last, Attribute& attr)
+    {
+        using namespace boost::spirit::qi;
+        using namespace boost::spirit;
+
+        uint_spec<unsigned, 10, 1, 3> uint3;
+        uint_spec<unsigned, 10, 3, 3> uint3_3;
+
+        T result = 0;
+        if (parse(first, last, uint3, result))
+        {
+            bool hit = false;
+            T n;
+            Iterator save = first;
+
+            while (parse(first, last, ',') && parse(first, last, uint3_3, n))
+            {
+                result = result * 1000 + n;
+                save = first;
+                hit = true;
+            }
+
+            first = save;
+            if (hit)
+                attr = result;
+            return hit;
+        }
+        return false;
+    }
+};
+
+template <typename T>
+struct no_trailing_dot_policy : boost::spirit::qi::real_policies<T>
+{
+    static bool const allow_trailing_dot = false;
+};
+
+template <typename T>
+struct no_leading_dot_policy : boost::spirit::qi::real_policies<T>
+{
+    static bool const allow_leading_dot = false;
+};
+
+template <typename T>
+bool
+compare(T n, double expected)
+{
+    double const eps = 0.00001;
+    T delta = n - expected;
+    return (delta >= -eps) && (delta <= eps);
+}
+
+int
+main()
+{
+    ///////////////////////////////////////////////////////////////////////////////
+    //  thousand separated numbers
+    ///////////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::qi::uint_spec;
+        using boost::spirit::qi::parse;
+
+        uint_spec<unsigned, 10, 1, 3> uint3;
+        uint_spec<unsigned, 10, 3, 3> uint3_3;
+
+    #define r (uint3 >> *(',' >> uint3_3))
+
+        BOOST_TEST(test("1,234,567,890", r));
+        BOOST_TEST(test("12,345,678,900", r));
+        BOOST_TEST(test("123,456,789,000", r));
+        BOOST_TEST(!test("1000,234,567,890", r));
+        BOOST_TEST(!test("1,234,56,890", r));
+        BOOST_TEST(!test("1,66", r));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    //  unsigned real number tests
+    ///////////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::qi::real_spec;
+        using boost::spirit::qi::parse;
+        using boost::spirit::qi::ureal_policies;
+
+        real_spec<double, ureal_policies<double> > udouble;
+        double  d;
+
+        BOOST_TEST(test("1234", udouble));
+        BOOST_TEST(test_attr("1234", udouble, d) && compare(d, 1234));
+
+        BOOST_TEST(test("1.2e3", udouble));
+        BOOST_TEST(test_attr("1.2e3", udouble, d) && compare(d, 1.2e3));
+
+        BOOST_TEST(test("1.2e-3", udouble));
+        BOOST_TEST(test_attr("1.2e-3", udouble, d) && compare(d, 1.2e-3));
+
+        BOOST_TEST(test("1.e2", udouble));
+        BOOST_TEST(test_attr("1.e2", udouble, d) && compare(d, 1.e2));
+
+        BOOST_TEST(test("1.", udouble));
+        BOOST_TEST(test_attr("1.", udouble, d) && compare(d, 1.));
+
+        BOOST_TEST(test(".2e3", udouble));
+        BOOST_TEST(test_attr(".2e3", udouble, d) && compare(d, .2e3));
+
+        BOOST_TEST(test("2e3", udouble));
+        BOOST_TEST(test_attr("2e3", udouble, d) && compare(d, 2e3));
+
+        BOOST_TEST(test("2", udouble));
+        BOOST_TEST(test_attr("2", udouble, d) && compare(d, 2));
+
+        using boost::math::fpclassify;
+        BOOST_TEST(test("inf", udouble));
+        BOOST_TEST(test("infinity", udouble));
+        BOOST_TEST(test("INF", udouble));
+        BOOST_TEST(test("INFINITY", udouble));
+        BOOST_TEST(test_attr("inf", udouble, d) && FP_INFINITE == fpclassify(d));
+        BOOST_TEST(test_attr("INF", udouble, d) && FP_INFINITE == fpclassify(d));
+        BOOST_TEST(test_attr("infinity", udouble, d) && FP_INFINITE == fpclassify(d));
+        BOOST_TEST(test_attr("INFINITY", udouble, d) && FP_INFINITE == fpclassify(d));
+
+        BOOST_TEST(test("nan", udouble));
+        BOOST_TEST(test_attr("nan", udouble, d) && FP_NAN == fpclassify(d));
+        BOOST_TEST(test("NAN", udouble));
+        BOOST_TEST(test_attr("NAN", udouble, d) && FP_NAN == fpclassify(d));
+
+        BOOST_TEST(test("nan(...)", udouble));
+        BOOST_TEST(test_attr("nan(...)", udouble, d) && FP_NAN == fpclassify(d));
+        BOOST_TEST(test("NAN(...)", udouble));
+        BOOST_TEST(test_attr("NAN(...)", udouble, d) && FP_NAN == fpclassify(d));
+
+        BOOST_TEST(!test("e3", udouble));
+        BOOST_TEST(!test_attr("e3", udouble, d));
+
+        BOOST_TEST(!test("-1.2e3", udouble));
+        BOOST_TEST(!test_attr("-1.2e3", udouble, d));
+
+        BOOST_TEST(!test("+1.2e3", udouble));
+        BOOST_TEST(!test_attr("+1.2e3", udouble, d));
+
+        BOOST_TEST(!test("1.2e", udouble));
+        BOOST_TEST(!test_attr("1.2e", udouble, d));
+
+        BOOST_TEST(!test("-.3", udouble));
+        BOOST_TEST(!test_attr("-.3", udouble, d));
+    }
+
+///////////////////////////////////////////////////////////////////////////////
+//  signed real number tests
+///////////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::double_;
+        using boost::spirit::qi::parse;
+        double  d;
+
+        BOOST_TEST(test("-1234", double_));
+        BOOST_TEST(test_attr("-1234", double_, d) && compare(d, -1234));
+
+        BOOST_TEST(test("-1.2e3", double_));
+        BOOST_TEST(test_attr("-1.2e3", double_, d) && compare(d, -1.2e3));
+
+        BOOST_TEST(test("+1.2e3", double_));
+        BOOST_TEST(test_attr("+1.2e3", double_, d) && compare(d, 1.2e3));
+
+        BOOST_TEST(test("-0.1", double_));
+        BOOST_TEST(test_attr("-0.1", double_, d) && compare(d, -0.1));
+
+        BOOST_TEST(test("-1.2e-3", double_));
+        BOOST_TEST(test_attr("-1.2e-3", double_, d) && compare(d, -1.2e-3));
+
+        BOOST_TEST(test("-1.e2", double_));
+        BOOST_TEST(test_attr("-1.e2", double_, d) && compare(d, -1.e2));
+
+        BOOST_TEST(test("-.2e3", double_));
+        BOOST_TEST(test_attr("-.2e3", double_, d) && compare(d, -.2e3));
+
+        BOOST_TEST(test("-2e3", double_));
+        BOOST_TEST(test_attr("-2e3", double_, d) && compare(d, -2e3));
+
+        BOOST_TEST(!test("-e3", double_));
+        BOOST_TEST(!test_attr("-e3", double_, d));
+
+        BOOST_TEST(!test("-1.2e", double_));
+        BOOST_TEST(!test_attr("-1.2e", double_, d));
+
+        using boost::math::fpclassify;
+        using boost::math::signbit;
+        BOOST_TEST(test("-inf", double_));
+        BOOST_TEST(test("-infinity", double_));
+        BOOST_TEST(test_attr("-inf", double_, d) &&
+            FP_INFINITE == fpclassify(d) && signbit(d));
+        BOOST_TEST(test_attr("-infinity", double_, d) &&
+            FP_INFINITE == fpclassify(d) && signbit(d));
+        BOOST_TEST(test("-INF", double_));
+        BOOST_TEST(test("-INFINITY", double_));
+        BOOST_TEST(test_attr("-INF", double_, d) &&
+            FP_INFINITE == fpclassify(d) && signbit(d));
+        BOOST_TEST(test_attr("-INFINITY", double_, d) &&
+            FP_INFINITE == fpclassify(d) && signbit(d));
+
+        BOOST_TEST(test("-nan", double_));
+        BOOST_TEST(test_attr("-nan", double_, d) &&
+            FP_NAN == fpclassify(d) && signbit(d));
+        BOOST_TEST(test("-NAN", double_));
+        BOOST_TEST(test_attr("-NAN", double_, d) &&
+            FP_NAN == fpclassify(d) && signbit(d));
+
+        BOOST_TEST(test("-nan(...)", double_));
+        BOOST_TEST(test_attr("-nan(...)", double_, d) &&
+            FP_NAN == fpclassify(d) && signbit(d));
+        BOOST_TEST(test("-NAN(...)", double_));
+        BOOST_TEST(test_attr("-NAN(...)", double_, d) &&
+            FP_NAN == fpclassify(d) && signbit(d));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////////
+    //  strict real number tests
+    ///////////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::qi::real_spec;
+        using boost::spirit::qi::parse;
+        using boost::spirit::qi::strict_ureal_policies;
+        using boost::spirit::qi::strict_real_policies;
+
+        real_spec<double, strict_ureal_policies<double> > strict_udouble;
+        real_spec<double, strict_real_policies<double> > strict_double;
+        double  d;
+
+        BOOST_TEST(!test("1234", strict_udouble));
+        BOOST_TEST(!test_attr("1234", strict_udouble, d));
+
+        BOOST_TEST(test("1.2", strict_udouble));
+        BOOST_TEST(test_attr("1.2", strict_udouble, d) && compare(d, 1.2));
+
+        BOOST_TEST(!test("-1234", strict_double));
+        BOOST_TEST(!test_attr("-1234", strict_double, d));
+
+        BOOST_TEST(test("123.", strict_double));
+        BOOST_TEST(test_attr("123.", strict_double, d) && compare(d, 123));
+
+        BOOST_TEST(test("3.E6", strict_double));
+        BOOST_TEST(test_attr("3.E6", strict_double, d) && compare(d, 3e6));
+
+        real_spec<double, no_trailing_dot_policy<double> > notrdot_real;
+        real_spec<double, no_leading_dot_policy<double> > nolddot_real;
+
+        BOOST_TEST(!test("1234.", notrdot_real));          //  Bad trailing dot
+        BOOST_TEST(!test(".1234", nolddot_real));          //  Bad leading dot
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  Special thousands separated numbers
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::qi::real_spec;
+        using boost::spirit::qi::parse;
+        real_spec<double, ts_real_policies<double> > ts_real;
+        double  d;
+
+        BOOST_TEST(test("123,456,789.01", ts_real));
+        BOOST_TEST(test_attr("123,456,789.01", ts_real, d) && compare(d, 123456789.01));
+
+        BOOST_TEST(test("12,345,678.90", ts_real));
+        BOOST_TEST(test_attr("12,345,678.90", ts_real, d) && compare(d, 12345678.90));
+
+        BOOST_TEST(test("1,234,567.89", ts_real));
+        BOOST_TEST(test_attr("1,234,567.89", ts_real, d) && compare(d, 1234567.89));
+
+        BOOST_TEST(!test("1234,567,890", ts_real));
+        BOOST_TEST(!test("1,234,5678,9", ts_real));
+        BOOST_TEST(!test("1,234,567.89e6", ts_real));
+        BOOST_TEST(!test("1,66", ts_real));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  Custom data type
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::math::concepts::real_concept;
+        using boost::spirit::qi::real_spec;
+        using boost::spirit::qi::real_policies;
+        using boost::spirit::qi::parse;
+        
+        real_spec<real_concept, real_policies<real_concept> > custom_real;
+        real_concept d;
+        
+        BOOST_TEST(test("-1234", custom_real));
+        BOOST_TEST(test_attr("-1234", custom_real, d) && compare(d, -1234));
+
+        BOOST_TEST(test("-1.2e3", custom_real));
+        BOOST_TEST(test_attr("-1.2e3", custom_real, d) && compare(d, -1.2e3));
+
+        BOOST_TEST(test("+1.2e3", custom_real));
+        BOOST_TEST(test_attr("+1.2e3", custom_real, d) && compare(d, 1.2e3));
+
+        BOOST_TEST(test("-0.1", custom_real));
+        BOOST_TEST(test_attr("-0.1", custom_real, d) && compare(d, -0.1));
+
+        BOOST_TEST(test("-1.2e-3", custom_real));
+        BOOST_TEST(test_attr("-1.2e-3", custom_real, d) && compare(d, -1.2e-3));
+
+        BOOST_TEST(test("-1.e2", custom_real));
+        BOOST_TEST(test_attr("-1.e2", custom_real, d) && compare(d, -1.e2));
+
+        BOOST_TEST(test("-.2e3", custom_real));
+        BOOST_TEST(test_attr("-.2e3", custom_real, d) && compare(d, -.2e3));
+
+        BOOST_TEST(test("-2e3", custom_real));
+        BOOST_TEST(test_attr("-2e3", custom_real, d) && compare(d, -2e3));
+
+        BOOST_TEST(!test("-e3", custom_real));
+        BOOST_TEST(!test_attr("-e3", custom_real, d));
+
+        BOOST_TEST(!test("-1.2e", custom_real));
+        BOOST_TEST(!test_attr("-1.2e", custom_real, d));
+    }
+    
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/rule.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/rule.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,227 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit::qi;
+    using namespace boost::spirit::ascii;
+
+    { // basic tests
+
+        rule<char const*> a, b, c, start;
+
+        a = 'a';
+        b = 'b';
+        c = 'c';
+
+        start = *(a | b | c);
+        BOOST_TEST(test("abcabcacb", start));
+
+        start = (a | b) >> (start | b);
+        BOOST_TEST(test("aaaabababaaabbb", start));
+        BOOST_TEST(test("aaaabababaaabba", start, false));
+    }
+
+    { // basic tests w/ skipper
+
+        rule<char const*, space_type> a, b, c, start;
+
+        a = 'a';
+        b = 'b';
+        c = 'c';
+
+        start = *(a | b | c);
+        BOOST_TEST(test(" a b c a b c a c b", start, space));
+
+        // allow no skipping too:
+        BOOST_TEST(test("abcabcacb", start));
+
+        start = (a | b) >> (start | b);
+        BOOST_TEST(test(" a a a a b a b a b a a a b b b ", start, space));
+        BOOST_TEST(test(" a a a a b a b a b a a a b b a ", start, space, false));
+    }
+
+    { // alias tests
+
+        rule<char const*> a, b, c, d, start;
+
+        a = 'a';
+        b = 'b';
+        c = 'c';
+        d = start.alias(); // d will always track start
+
+        start = *(a | b | c);
+        BOOST_TEST(test("abcabcacb", d));
+
+        start = (a | b) >> (start | b);
+        BOOST_TEST(test("aaaabababaaabbb", d));
+    }
+
+    { // copy tests
+
+        rule<char const*> a, b, c, start;
+
+        a = 'a';
+        b = 'b';
+        c = 'c';
+
+        // The FF is the dynamic equivalent of start = *(a | b | c);
+        start = a;
+        start = start.copy() | b;
+        start = start.copy() | c;
+        start = *(start.copy());
+
+        BOOST_TEST(test("abcabcacb", start));
+
+        // The FF is the dynamic equivalent of start = (a | b) >> (start | b);
+        start = b;
+        start = a | start.copy();
+        start = start.copy() >> (start | b);
+
+        BOOST_TEST(test("aaaabababaaabbb", start));
+        BOOST_TEST(test("aaaabababaaabba", start, false));
+    }
+
+    { // context tests
+
+        using namespace boost::phoenix;
+        using namespace boost::spirit::ascii;
+        using boost::spirit::arg_names::_1;
+        using boost::spirit::arg_names::_val;
+
+        char ch;
+        rule<char const*, char()> a;
+        a = alpha[_val = _1];
+
+        BOOST_TEST(test("x", a[ref(ch) = _1]));
+        BOOST_TEST(ch == 'x');
+
+        BOOST_TEST(test_attr("z", a, ch)); // attribute is given.
+        BOOST_TEST(ch == 'z');
+    }
+
+    { // context (w/arg) tests
+
+        using namespace boost::phoenix;
+        using namespace boost::spirit::ascii;
+        using boost::spirit::arg_names::_1;
+        using boost::spirit::arg_names::_r1;
+        using boost::spirit::arg_names::_r2;
+        using boost::spirit::arg_names::_val;
+
+        char ch;
+        rule<char const*, char(int)> a; // 1 arg
+        a = alpha[_val = _1 + _r1];
+
+        BOOST_TEST(test("x", a(val(1))[ref(ch) = _1]));
+        BOOST_TEST(ch == 'x' + 1);
+
+        BOOST_TEST(test_attr("a", a(1), ch)); // allow scalars as rule args too.
+        BOOST_TEST(ch == 'a' + 1);
+
+        rule<char const*, char(int, int)> b; // 2 args
+        b = alpha[_val = _1 + _r1 + _r2];
+        BOOST_TEST(test_attr("a", b(1, 2), ch));
+        BOOST_TEST(ch == 'a' + 1 + 2);
+    }
+
+    { // context (w/locals) tests
+        using namespace boost::phoenix;
+        using namespace boost::spirit::ascii;
+        using boost::spirit::arg_names::_1;
+        using boost::spirit::arg_names::_a;
+        using boost::spirit::char_;
+        using boost::spirit::locals;
+
+        rule<char const*, locals<char> > a; // 1 local
+        a = alpha[_a = _1] >> char_(_a);
+        BOOST_TEST(test("aa", a));
+        BOOST_TEST(!test("ax", a));
+    }
+
+    { // context (w/args and locals) tests
+        using namespace boost::phoenix;
+        using namespace boost::spirit::ascii;
+        using boost::spirit::arg_names::_1;
+        using boost::spirit::arg_names::_r1;
+        using boost::spirit::arg_names::_a;
+        using boost::spirit::char_;
+        using boost::spirit::locals;
+
+        rule<char const*, void(int), locals<char> > a; // 1 arg + 1 local
+        a = alpha[_a = _1 + _r1] >> char_(_a);
+        BOOST_TEST(test("ab", a(val(1))));
+        BOOST_TEST(test("xy", a(val(1))));
+        BOOST_TEST(!test("ax", a(val(1))));
+    }
+
+    { // bug: test that injected attributes are ok
+        using namespace boost::phoenix;
+        using namespace boost::spirit::ascii;
+        using boost::spirit::arg_names::_1;
+        using boost::spirit::arg_names::_r1;
+        using boost::spirit::arg_names::_val;
+        using boost::spirit::char_;
+
+        rule<char const*, char(int) > r;
+
+        // problem code:
+        r = char_(_r1)[_val = _1];
+    }
+
+    { // error handling
+
+        using namespace boost::phoenix;
+        using namespace boost::spirit::ascii;
+        using boost::phoenix::val;
+        using boost::spirit::int_;
+        using boost::spirit::arg_names::_4; // what
+        using boost::spirit::arg_names::_3; // error pos
+        using boost::spirit::arg_names::_2; // end
+        using boost::spirit::qi::fail;
+
+        rule<char const*> r;
+        r = '(' > int_ > ',' > int_ > ')';
+
+        on_error<fail>
+        (
+            r, std::cout
+                << val("Error! Expecting: ")
+                << _4
+                << val(" Here: \"")
+                << construct<std::string>(_3, _2)
+                << val("\"")
+                << std::endl
+        );
+
+        BOOST_TEST(test("(123,456)", r));
+        BOOST_TEST(!test("(abc,def)", r));
+        BOOST_TEST(!test("(123,456]", r));
+        BOOST_TEST(!test("(123;456)", r));
+        BOOST_TEST(!test("[123,456]", r));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/rule_fail.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/rule_fail.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,31 @@
+/*=============================================================================
+    Copyright (c) 2001-2008 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 <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace boost::spirit::ascii;
+
+// this test must fail compiling
+int main()
+{
+    char const* input = "some input, it doesn't matter";
+    char const* end = &input[strlen(input)+1];
+    
+    rule<char const*, rule<char const*> > def;
+    def = int_ >> *(',' >> int_);
+    
+    bool r = phrase_parse(input, end, def,
+		    space | ('%' >> *~char_('\n') >> '\n'));
+
+    return 0;
+}
Added: trunk/libs/spirit/test/qi/sequence.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/sequence.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,204 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using namespace boost::spirit::ascii;
+    using boost::fusion::vector;
+    using boost::fusion::at_c;
+    using spirit_test::test;
+    using spirit_test::test_attr;
+
+    {
+        BOOST_TEST((test("aa", char_ >> char_)));
+        BOOST_TEST((test("aaa", char_ >> char_ >> char_('a'))));
+        BOOST_TEST((test("xi", char_('x') >> char_('i'))));
+        BOOST_TEST((!test("xi", char_('x') >> char_('o'))));
+        BOOST_TEST((test("xin", char_('x') >> char_('i') >> char_('n'))));
+
+    }
+
+    {
+        BOOST_TEST((test(" a a ", char_ >> char_, space)));
+        BOOST_TEST((test(" x i ", char_('x') >> char_('i'), space)));
+        BOOST_TEST((!test(" x i ", char_('x') >> char_('o'), space)));
+    }
+
+    {
+        BOOST_TEST((test(" Hello, World", lit("Hello") >> ',' >> "World", space)));
+    }
+
+    {
+        vector<char, char> attr;
+        BOOST_TEST((test_attr("abcdefg", char_ >> char_ >> "cdefg", attr)));
+        BOOST_TEST((at_c<0>(attr) == 'a'));
+        BOOST_TEST((at_c<1>(attr) == 'b'));
+    }
+
+    {
+        vector<char, char, char> attr;
+        BOOST_TEST((test_attr(" a\n  b\n  c\n ", char_ >> char_ >> char_, attr, space)));
+        BOOST_TEST((at_c<0>(attr) == 'a'));
+        BOOST_TEST((at_c<1>(attr) == 'b'));
+        BOOST_TEST((at_c<2>(attr) == 'c'));
+    }
+
+    {
+        // unused_type means we don't care about the attribute
+        vector<char, char> attr;
+        BOOST_TEST((test_attr("abc", char_ >> 'b' >> char_, attr)));
+        BOOST_TEST((at_c<0>(attr) == 'a'));
+        BOOST_TEST((at_c<1>(attr) == 'c'));
+    }
+
+    {
+        // omit[] means we don't receive the attribute
+        vector<char> attr;
+        BOOST_TEST((test_attr("abc", omit[char_] >> omit['b'] >> char_, attr)));
+        BOOST_TEST((at_c<0>(attr) == 'c'));
+    }
+
+    {
+        // If all elements except 1 is omitted, the attribute is
+        // a single-element sequence. For this case alone, we allow
+        // naked attributes (unwrapped in a fusion sequence).
+        char attr;
+        BOOST_TEST((test_attr("abc", omit[char_] >> 'b' >> char_, attr)));
+        BOOST_TEST((attr == 'c'));
+    }
+
+    {
+        // omit[] means we don't receive the attribute
+        vector<> attr;
+        BOOST_TEST((test_attr("abc", omit[char_] >> omit['b'] >> omit[char_], attr)));
+    }
+
+    {
+        // omit[] means we don't receive the attribute
+        // this test is merely a compile test, because using a unused as the
+        // explicit attribute doesn't make any sense
+        unused_type attr;
+        BOOST_TEST((test_attr("abc", omit[char_ >> 'b' >> char_], attr)));
+    }
+
+    {
+        // omit[] means we don't receive the attribute, if all elements of a
+        // sequence have unused attributes, the whole sequence has an unused
+        // attribute as well
+        vector<char, char> attr;
+        BOOST_TEST((test_attr("abcde",
+            char_ >> (omit[char_] >> omit['c'] >> omit[char_]) >> char_, attr)));
+        BOOST_TEST((at_c<0>(attr) == 'a'));
+        BOOST_TEST((at_c<1>(attr) == 'e'));
+    }
+
+    {
+        // "hello" has an unused_type. unused attrubutes are not part of the sequence
+        vector<char, char> attr;
+        BOOST_TEST((test_attr("a hello c", char_ >> "hello" >> char_, attr, space)));
+        BOOST_TEST((at_c<0>(attr) == 'a'));
+        BOOST_TEST((at_c<1>(attr) == 'c'));
+    }
+
+    {
+        // omit[] means we don't receive the attribute
+        vector<char> attr;
+        BOOST_TEST((test_attr("a hello c", char_ >> "hello" >> omit[char_], attr, space)));
+        BOOST_TEST((at_c<0>(attr) == 'a'));
+    }
+
+    {
+        // if only one node in a sequence is left (all the others are omitted),
+        // then we should also allow "naked" attributes (unwraped in a tuple)
+        int attr;
+        BOOST_TEST((test_attr("a 123 c", omit['a'] >> int_ >> omit['c'], attr, space)));
+        BOOST_TEST((attr == 123));
+    }
+
+    {
+        // unused means we don't care about the attribute
+        BOOST_TEST((test_attr("abc", char_ >> 'b' >> char_, unused)));
+    }
+
+    {
+        BOOST_TEST((test("aA", no_case[char_('a') >> 'a'])));
+        BOOST_TEST((test("BEGIN END", no_case[lit("begin") >> "end"], space)));
+        BOOST_TEST((!test("BEGIN END", no_case[lit("begin") >> "nend"], space)));
+    }
+
+    {
+#ifdef SPIRIT_TEST_COMPILE_FAIL // $$$
+        char_ >> char_ = char_ >> char_; // disallow this!
+#endif
+    }
+
+    {   // test action
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        char c = 0;
+        int n = 0;
+
+        BOOST_TEST(test("x123\"a string\"", (char_ >> int_ >> "\"a string\"")
+            [ref(c) = _1, ref(n) = _2]));
+        BOOST_TEST(c == 'x');
+        BOOST_TEST(n == 123);
+    }
+
+    {   // test action with omitted attribute
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        char c = 0;
+
+        BOOST_TEST(test("x123\"a string\"", (char_ >> omit[int_] >> "\"a string\"")
+            [ref(c) = _1]));
+        BOOST_TEST(c == 'x');
+    }
+
+    {   // test action
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        char c = 0;
+        int n = 0;
+
+        BOOST_TEST(test("x 123 \"a string\"", (char_ >> int_ >> "\"a string\"")
+            [ref(c) = _1, ref(n) = _2], space));
+        BOOST_TEST(c == 'x');
+        BOOST_TEST(n == 123);
+    }
+
+    {   // test action with omitted attribute
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        int n = 0;
+
+        BOOST_TEST(test("x 123 \"a string\"",
+            (omit[char_] >> int_ >> "\"a string\"")[ref(n) = _1], space));
+        BOOST_TEST(n == 123);
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/sequential_or.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/sequential_or.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,77 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/fusion/include/at.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/optional.hpp>
+
+#include <string>
+#include <iostream>
+#include "test.hpp"
+
+using namespace spirit_test;
+
+int
+main()
+{
+    using namespace boost::spirit;
+    using boost::spirit::ascii::alpha;
+    using boost::fusion::vector;
+    using boost::fusion::at_c;
+    using boost::optional;
+
+    {
+        BOOST_TEST((test("a", char_('a') || char_('b'))));
+        BOOST_TEST((test("b", char_('a') || char_('b'))));
+        BOOST_TEST((test("ab", char_('a') || char_('b'))));
+    }
+
+    {
+        vector<optional<int>, optional<char> > attr;
+
+        BOOST_TEST((test_attr("a", int_ || alpha, attr)));
+        BOOST_TEST((!at_c<0>(attr)));
+        BOOST_TEST((at_c<1>(attr).get() == 'a'));
+
+        at_c<1>(attr) = optional<char>(); // clear the optional
+        BOOST_TEST((test_attr("123", int_ || alpha, attr)));
+        BOOST_TEST((at_c<0>(attr).get() == 123));
+        BOOST_TEST((!at_c<1>(attr)));
+
+        at_c<0>(attr) = optional<int>(); // clear the optional
+        BOOST_TEST((test_attr("123a", int_ || alpha, attr)));
+        BOOST_TEST((at_c<0>(attr).get() == 123));
+        BOOST_TEST((at_c<1>(attr).get() == 'a'));
+
+        BOOST_TEST((!test("a123", int_ || alpha)));
+    }
+
+    {   // test action
+        using namespace boost::phoenix;
+        using namespace boost::spirit::arg_names;
+        namespace phx = boost::phoenix;
+
+        optional<int> i;
+        optional<char> c;
+
+        BOOST_TEST((test("123a", (int_ || alpha)[phx::ref(i) = _1, phx::ref(c) = _2])));
+        BOOST_TEST((i.get() == 123));
+        BOOST_TEST((c.get() == 'a'));
+    }
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/symbols.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/symbols.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,189 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_string.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/qi_directive.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include "test.hpp"
+
+int
+main()
+{
+    using spirit_test::test;
+    using spirit_test::test_attr;
+    using namespace boost::spirit::qi;
+
+    { // basics
+        symbols<char, int> sym;
+
+        sym.add
+            ("Joel")
+            ("Ruby")
+            ("Tenji")
+            ("Tutit")
+            ("Kim")
+            ("Joey")
+        ;
+
+        BOOST_TEST((test("Joel", sym)));
+        BOOST_TEST((test("Ruby", sym)));
+        BOOST_TEST((test("Tenji", sym)));
+        BOOST_TEST((test("Tutit", sym)));
+        BOOST_TEST((test("Kim", sym)));
+        BOOST_TEST((test("Joey", sym)));
+        BOOST_TEST((!test("XXX", sym)));
+
+        sym.remove
+            ("Joel")
+            ("Ruby")
+        ;
+
+        BOOST_TEST((!test("Joel", sym)));
+        BOOST_TEST((!test("Ruby", sym)));
+    }
+
+    { // comma syntax
+        symbols<char, int> sym;
+        sym += "Joel", "Ruby", "Tenji", "Tutit", "Kim", "Joey";
+
+        BOOST_TEST((test("Joel", sym)));
+        BOOST_TEST((test("Ruby", sym)));
+        BOOST_TEST((test("Tenji", sym)));
+        BOOST_TEST((test("Tutit", sym)));
+        BOOST_TEST((test("Kim", sym)));
+        BOOST_TEST((test("Joey", sym)));
+        BOOST_TEST((!test("XXX", sym)));
+
+        sym -= "Joel", "Ruby";
+
+        BOOST_TEST((!test("Joel", sym)));
+        BOOST_TEST((!test("Ruby", sym)));
+    }
+
+    { // no-case handling
+        using namespace boost::spirit::ascii;
+
+        symbols<char, int> sym;
+        // NOTE: make sure all entries are in lower-case!!!
+        sym = "joel", "ruby", "tenji", "tutit", "kim", "joey";
+
+        BOOST_TEST((test("joel", no_case[sym])));
+        BOOST_TEST((test("ruby", no_case[sym])));
+        BOOST_TEST((test("tenji", no_case[sym])));
+        BOOST_TEST((test("tutit", no_case[sym])));
+        BOOST_TEST((test("kim", no_case[sym])));
+        BOOST_TEST((test("joey", no_case[sym])));
+
+        BOOST_TEST((test("JOEL", no_case[sym])));
+        BOOST_TEST((test("RUBY", no_case[sym])));
+        BOOST_TEST((test("TENJI", no_case[sym])));
+        BOOST_TEST((test("TUTIT", no_case[sym])));
+        BOOST_TEST((test("KIM", no_case[sym])));
+        BOOST_TEST((test("JOEY", no_case[sym])));
+    }
+
+    { // attributes
+        symbols<char, int> sym;
+
+        sym.add
+            ("Joel", 1)
+            ("Ruby", 2)
+            ("Tenji", 3)
+            ("Tutit", 4)
+            ("Kim", 5)
+            ("Joey", 6)
+        ;
+
+        int i;
+        BOOST_TEST((test_attr("Joel", sym, i)));
+        BOOST_TEST(i == 1);
+        BOOST_TEST((test_attr("Ruby", sym, i)));
+        BOOST_TEST(i == 2);
+        BOOST_TEST((test_attr("Tenji", sym, i)));
+        BOOST_TEST(i == 3);
+        BOOST_TEST((test_attr("Tutit", sym, i)));
+        BOOST_TEST(i == 4);
+        BOOST_TEST((test_attr("Kim", sym, i)));
+        BOOST_TEST(i == 5);
+        BOOST_TEST((test_attr("Joey", sym, i)));
+        BOOST_TEST(i == 6);
+        BOOST_TEST((!test_attr("XXX", sym, i)));
+    }
+
+    { // actions
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+
+        symbols<char, int> sym;
+        sym.add
+            ("Joel", 1)
+            ("Ruby", 2)
+            ("Tenji", 3)
+            ("Tutit", 4)
+            ("Kim", 5)
+            ("Joey", 6)
+        ;
+
+        int i;
+        BOOST_TEST((test("Joel", sym[ref(i) = _1])));
+        BOOST_TEST(i == 1);
+        BOOST_TEST((test("Ruby", sym[ref(i) = _1])));
+        BOOST_TEST(i == 2);
+        BOOST_TEST((test("Tenji", sym[ref(i) = _1])));
+        BOOST_TEST(i == 3);
+        BOOST_TEST((test("Tutit", sym[ref(i) = _1])));
+        BOOST_TEST(i == 4);
+        BOOST_TEST((test("Kim", sym[ref(i) = _1])));
+        BOOST_TEST(i == 5);
+        BOOST_TEST((test("Joey", sym[ref(i) = _1])));
+        BOOST_TEST(i == 6);
+        BOOST_TEST((!test("XXX", sym[ref(i) = _1])));
+    }
+
+    { // construction from symbol array
+        char const* syms[] = {"Joel","Ruby","Tenji","Tutit","Kim","Joey"};
+        symbols<char, int> sym(syms);
+
+        BOOST_TEST((test("Joel", sym)));
+        BOOST_TEST((test("Ruby", sym)));
+        BOOST_TEST((test("Tenji", sym)));
+        BOOST_TEST((test("Tutit", sym)));
+        BOOST_TEST((test("Kim", sym)));
+        BOOST_TEST((test("Joey", sym)));
+        BOOST_TEST((!test("XXX", sym)));
+    }
+
+    { // construction from 2 arrays
+
+        char const* syms[] = {"Joel","Ruby","Tenji","Tutit","Kim","Joey"};
+        int data[] = {1,2,3,4,5,6};
+        symbols<char, int> sym(syms, data);
+
+        int i;
+        BOOST_TEST((test_attr("Joel", sym, i)));
+        BOOST_TEST(i == 1);
+        BOOST_TEST((test_attr("Ruby", sym, i)));
+        BOOST_TEST(i == 2);
+        BOOST_TEST((test_attr("Tenji", sym, i)));
+        BOOST_TEST(i == 3);
+        BOOST_TEST((test_attr("Tutit", sym, i)));
+        BOOST_TEST(i == 4);
+        BOOST_TEST((test_attr("Kim", sym, i)));
+        BOOST_TEST(i == 5);
+        BOOST_TEST((test_attr("Joey", sym, i)));
+        BOOST_TEST(i == 6);
+        BOOST_TEST((!test_attr("XXX", sym, i)));
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/qi/test.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/test.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,75 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_TEST_FEB_01_2007_0605PM)
+#define BOOST_SPIRIT_TEST_FEB_01_2007_0605PM
+
+#include <boost/spirit/include/qi_parse.hpp>
+#include <boost/spirit/include/qi_what.hpp>
+
+namespace spirit_test
+{
+    template <typename Char, typename Parser>
+    bool test(Char const* in, Parser const& p, bool full_match = true)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all parsers have it:
+        boost::spirit::qi::what(p);
+
+        Char const* last = in;
+        while (*last)
+            last++;
+        return boost::spirit::qi::parse(in, last, p)
+            && (!full_match || (in == last));
+    }
+
+    template <typename Char, typename Parser, typename Skipper>
+    bool test(Char const* in, Parser const& p
+        , Skipper const& s, bool full_match = true)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all parsers have it:
+        boost::spirit::qi::what(p);
+
+        Char const* last = in;
+        while (*last)
+            last++;
+        return boost::spirit::qi::phrase_parse(in, last, p, s)
+            && (!full_match || (in == last));
+    }
+
+    template <typename Char, typename Parser, typename Attr>
+    bool test_attr(Char const* in, Parser const& p
+        , Attr& attr, bool full_match = true)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all parsers have it:
+        boost::spirit::qi::what(p);
+
+        Char const* last = in;
+        while (*last)
+            last++;
+        return boost::spirit::qi::parse(in, last, p, attr)
+            && (!full_match || (in == last));
+    }
+
+    template <typename Char, typename Parser, typename Attr, typename Skipper>
+    bool test_attr(Char const* in, Parser const& p
+        , Attr& attr, Skipper const& s, bool full_match = true)
+    {
+        // we don't care about the result of the "what" function.
+        // we only care that all parsers have it:
+        boost::spirit::qi::what(p);
+
+        Char const* last = in;
+        while (*last)
+            last++;
+        return boost::spirit::qi::phrase_parse(in, last, p, attr, s)
+            && (!full_match || (in == last));
+    }
+}
+
+#endif
Added: trunk/libs/spirit/test/qi/tst.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/tst.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,354 @@
+/*=============================================================================
+    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)
+=============================================================================*/
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/qi/string/tst.hpp>
+#include <boost/spirit/qi/string/tst_map.hpp>
+
+#include <string>
+#include <cctype>
+#include <iostream>
+
+namespace
+{
+    template <typename TST, typename Char>
+    void add(TST& tst, Char const* s, int data)
+    {
+        Char const* last = s;
+        while (*last)
+            last++;
+        tst.add(s, last, data);
+    }
+
+    template <typename TST, typename Char>
+    void remove(TST& tst, Char const* s)
+    {
+        Char const* last = s;
+        while (*last)
+            last++;
+        tst.remove(s, last);
+    }
+
+    template <typename TST, typename Char>
+    void check(TST const& tst, Char const* s, bool expected, int N = 0, int val = -1)
+    {
+        Char const* first = s;
+        Char const* last = s;
+        while (*last)
+            last++;
+        int* r = tst.find(s, last);
+        BOOST_TEST((r != 0) == expected);
+        if (r != 0)
+            BOOST_TEST((s-first) == N);
+        if (r)
+            BOOST_TEST(*r == val);
+    }
+
+    struct printer
+    {
+        template <typename String, typename Data>
+        void operator()(String const& s, Data const& data)
+        {
+            std::cout << "    " << s << ": " << data << std::endl;
+        }
+    };
+
+    template <typename TST>
+    void print(TST const& tst)
+    {
+        std::cout << '[' << std::endl;
+        tst.for_each(printer());
+        std::cout << ']' << std::endl;
+    }
+
+    struct no_case_filter
+    {
+        template <typename Char>
+        Char operator()(Char ch) const
+        {
+            return std::tolower(ch);
+        }
+    };
+
+    template <typename TST, typename Char>
+    void nc_check(TST const& tst, Char const* s, bool expected, int N = 0, int val = -1)
+    {
+        Char const* first = s;
+        Char const* last = s;
+        while (*last)
+            last++;
+        int* r = tst.find(s, last, no_case_filter());
+        BOOST_TEST((r != 0) == expected);
+        if (r != 0)
+            BOOST_TEST((s-first) == N);
+        if (r)
+            BOOST_TEST(*r == val);
+    }
+}
+
+template <typename Lookup, typename WideLookup>
+void tests()
+{
+    { // basic tests
+        Lookup lookup;
+
+        check(lookup, "not-yet-there", false);
+        check(lookup, "", false);
+
+        add(lookup, "apple", 123);
+        check(lookup, "apple", true, 5, 123); // full match
+        check(lookup, "banana", false); // no-match
+        check(lookup, "applexxx", true, 5, 123); // partial match
+
+        add(lookup, "applepie", 456);
+        check(lookup, "applepie", true, 8, 456); // full match
+        check(lookup, "banana", false); // no-match
+        check(lookup, "applepiexxx", true, 8, 456); // partial match
+        check(lookup, "apple", true, 5, 123); // full match
+        check(lookup, "applexxx", true, 5, 123); // partial match
+    }
+
+    { // variation of above
+        Lookup lookup;
+
+        add(lookup, "applepie", 456);
+        add(lookup, "apple", 123);
+
+        check(lookup, "applepie", true, 8, 456); // full match
+        check(lookup, "banana", false); // no-match
+        check(lookup, "applepiexxx", true, 8, 456); // partial match
+        check(lookup, "apple", true, 5, 123); // full match
+        check(lookup, "applexxx", true, 5, 123); // partial match
+    }
+    { // variation of above
+        Lookup lookup;
+
+        add(lookup, "applepie", 456);
+        add(lookup, "apple", 123);
+
+        check(lookup, "applepie", true, 8, 456); // full match
+        check(lookup, "banana", false); // no-match
+        check(lookup, "applepiexxx", true, 8, 456); // partial match
+        check(lookup, "apple", true, 5, 123); // full match
+        check(lookup, "applexxx", true, 5, 123); // partial match
+    }
+
+    { // narrow char tests
+        Lookup lookup;
+        add(lookup, "pineapple", 1);
+        add(lookup, "orange", 2);
+        add(lookup, "banana", 3);
+        add(lookup, "applepie", 4);
+        add(lookup, "apple", 5);
+
+        check(lookup, "pineapple", true, 9, 1);
+        check(lookup, "orange", true, 6, 2);
+        check(lookup, "banana", true, 6, 3);
+        check(lookup, "apple", true, 5, 5);
+        check(lookup, "pizza", false);
+        check(lookup, "steak", false);
+        check(lookup, "applepie", true, 8, 4);
+        check(lookup, "bananarama", true, 6, 3);
+        check(lookup, "applet", true, 5, 5);
+        check(lookup, "applepi", true, 5, 5);
+        check(lookup, "appl", false);
+
+        check(lookup, "pineapplez", true, 9, 1);
+        check(lookup, "orangez", true, 6, 2);
+        check(lookup, "bananaz", true, 6, 3);
+        check(lookup, "applez", true, 5, 5);
+        check(lookup, "pizzaz", false);
+        check(lookup, "steakz", false);
+        check(lookup, "applepiez", true, 8, 4);
+        check(lookup, "bananaramaz", true, 6, 3);
+        check(lookup, "appletz", true, 5, 5);
+        check(lookup, "applepix", true, 5, 5);
+    }
+
+    { // wide char tests
+        WideLookup lookup;
+        add(lookup, L"pineapple", 1);
+        add(lookup, L"orange", 2);
+        add(lookup, L"banana", 3);
+        add(lookup, L"applepie", 4);
+        add(lookup, L"apple", 5);
+
+        check(lookup, L"pineapple", true, 9, 1);
+        check(lookup, L"orange", true, 6, 2);
+        check(lookup, L"banana", true, 6, 3);
+        check(lookup, L"apple", true, 5, 5);
+        check(lookup, L"pizza", false);
+        check(lookup, L"steak", false);
+        check(lookup, L"applepie", true, 8, 4);
+        check(lookup, L"bananarama", true, 6, 3);
+        check(lookup, L"applet", true, 5, 5);
+        check(lookup, L"applepi", true, 5, 5);
+        check(lookup, L"appl", false);
+
+        check(lookup, L"pineapplez", true, 9, 1);
+        check(lookup, L"orangez", true, 6, 2);
+        check(lookup, L"bananaz", true, 6, 3);
+        check(lookup, L"applez", true, 5, 5);
+        check(lookup, L"pizzaz", false);
+        check(lookup, L"steakz", false);
+        check(lookup, L"applepiez", true, 8, 4);
+        check(lookup, L"bananaramaz", true, 6, 3);
+        check(lookup, L"appletz", true, 5, 5);
+        check(lookup, L"applepix", true, 5, 5);
+    }
+
+    { // test remove
+        Lookup lookup;
+        add(lookup, "pineapple", 1);
+        add(lookup, "orange", 2);
+        add(lookup, "banana", 3);
+        add(lookup, "applepie", 4);
+        add(lookup, "apple", 5);
+
+        check(lookup, "pineapple", true, 9, 1);
+        check(lookup, "orange", true, 6, 2);
+        check(lookup, "banana", true, 6, 3);
+        check(lookup, "apple", true, 5, 5);
+        check(lookup, "applepie", true, 8, 4);
+        check(lookup, "bananarama", true, 6, 3);
+        check(lookup, "applet", true, 5, 5);
+        check(lookup, "applepi", true, 5, 5);
+        check(lookup, "appl", false);
+
+        remove(lookup, "banana");
+        check(lookup, "pineapple", true, 9, 1);
+        check(lookup, "orange", true, 6, 2);
+        check(lookup, "banana", false);
+        check(lookup, "apple", true, 5, 5);
+        check(lookup, "applepie", true, 8, 4);
+        check(lookup, "bananarama", false);
+        check(lookup, "applet", true, 5, 5);
+        check(lookup, "applepi", true, 5, 5);
+        check(lookup, "appl", false);
+
+        remove(lookup, "apple");
+        check(lookup, "pineapple", true, 9, 1);
+        check(lookup, "orange", true, 6, 2);
+        check(lookup, "apple", false);
+        check(lookup, "applepie", true, 8, 4);
+        check(lookup, "applet", false);
+        check(lookup, "applepi", false);
+        check(lookup, "appl", false);
+
+        remove(lookup, "orange");
+        check(lookup, "pineapple", true, 9, 1);
+        check(lookup, "orange", false);
+        check(lookup, "applepie", true, 8, 4);
+
+        remove(lookup, "pineapple");
+        check(lookup, "pineapple", false);
+        check(lookup, "orange", false);
+        check(lookup, "applepie", true, 8, 4);
+
+        remove(lookup, "applepie");
+        check(lookup, "applepie", false);
+    }
+
+    { // copy/assign/clear test
+        Lookup lookupa;
+        add(lookupa, "pineapple", 1);
+        add(lookupa, "orange", 2);
+        add(lookupa, "banana", 3);
+        add(lookupa, "applepie", 4);
+        add(lookupa, "apple", 5);
+
+        Lookup lookupb(lookupa); // copy ctor
+        check(lookupb, "pineapple", true, 9, 1);
+        check(lookupb, "orange", true, 6, 2);
+        check(lookupb, "banana", true, 6, 3);
+        check(lookupb, "apple", true, 5, 5);
+        check(lookupb, "pizza", false);
+        check(lookupb, "steak", false);
+        check(lookupb, "applepie", true, 8, 4);
+        check(lookupb, "bananarama", true, 6, 3);
+        check(lookupb, "applet", true, 5, 5);
+        check(lookupb, "applepi", true, 5, 5);
+        check(lookupb, "appl", false);
+
+        lookupb.clear(); // clear
+        check(lookupb, "pineapple", false);
+        check(lookupb, "orange", false);
+        check(lookupb, "banana", false);
+        check(lookupb, "apple", false);
+        check(lookupb, "applepie", false);
+        check(lookupb, "bananarama", false);
+        check(lookupb, "applet", false);
+        check(lookupb, "applepi", false);
+        check(lookupb, "appl", false);
+
+        lookupb = lookupa; // assign
+        check(lookupb, "pineapple", true, 9, 1);
+        check(lookupb, "orange", true, 6, 2);
+        check(lookupb, "banana", true, 6, 3);
+        check(lookupb, "apple", true, 5, 5);
+        check(lookupb, "pizza", false);
+        check(lookupb, "steak", false);
+        check(lookupb, "applepie", true, 8, 4);
+        check(lookupb, "bananarama", true, 6, 3);
+        check(lookupb, "applet", true, 5, 5);
+        check(lookupb, "applepi", true, 5, 5);
+        check(lookupb, "appl", false);
+    }
+
+    { // test for_each
+        Lookup lookup;
+        add(lookup, "pineapple", 1);
+        add(lookup, "orange", 2);
+        add(lookup, "banana", 3);
+        add(lookup, "applepie", 4);
+        add(lookup, "apple", 5);
+
+        print(lookup);
+    }
+
+    { // case insensitive tests
+        Lookup lookup;
+
+        // NOTE: make sure all entries are in lower-case!!!
+        add(lookup, "pineapple", 1);
+        add(lookup, "orange", 2);
+        add(lookup, "banana", 3);
+        add(lookup, "applepie", 4);
+        add(lookup, "apple", 5);
+
+        nc_check(lookup, "pineapple", true, 9, 1);
+        nc_check(lookup, "orange", true, 6, 2);
+        nc_check(lookup, "banana", true, 6, 3);
+        nc_check(lookup, "apple", true, 5, 5);
+        nc_check(lookup, "applepie", true, 8, 4);
+
+        nc_check(lookup, "PINEAPPLE", true, 9, 1);
+        nc_check(lookup, "ORANGE", true, 6, 2);
+        nc_check(lookup, "BANANA", true, 6, 3);
+        nc_check(lookup, "APPLE", true, 5, 5);
+        nc_check(lookup, "APPLEPIE", true, 8, 4);
+
+        nc_check(lookup, "pineApple", true, 9, 1);
+        nc_check(lookup, "orangE", true, 6, 2);
+        nc_check(lookup, "Banana", true, 6, 3);
+        nc_check(lookup, "aPPLe", true, 5, 5);
+        nc_check(lookup, "ApplePie", true, 8, 4);
+
+        print(lookup);
+    }
+}
+
+int
+main()
+{
+    using namespace boost::spirit::qi;
+
+    tests<tst<char, int>, tst<wchar_t, int> >();
+    tests<tst_map<char, int>, tst_map<wchar_t, int> >();
+
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/qi/uint.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/qi/uint.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,175 @@
+/*=============================================================================
+    Copyright (c) 2001-2007 Joel de Guzman
+    Copyright (c) 2001-2007 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 <climits>
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_action.hpp>
+#include <boost/spirit/include/support_argument.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include "test.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+//
+//  *** BEWARE PLATFORM DEPENDENT!!! ***
+//  *** The following assumes 32 bit integers and 64 bit long longs.
+//  *** Modify these constant strings when appropriate.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+    char const* max_unsigned = "4294967295";
+    char const* unsigned_overflow = "4294967296";
+    char const* max_int = "2147483647";
+    char const* int_overflow = "2147483648";
+    char const* min_int = "-2147483648";
+    char const* int_underflow = "-2147483649";
+    char const* max_binary = "11111111111111111111111111111111";
+    char const* binary_overflow = "100000000000000000000000000000000";
+    char const* max_octal = "37777777777";
+    char const* octal_overflow = "100000000000";
+    char const* max_hex = "FFFFFFFF";
+    char const* hex_overflow = "100000000";
+
+int
+main()
+{
+    using namespace spirit_test;
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  unsigned tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::uint;
+        unsigned u;
+
+        BOOST_TEST(test("123456", uint));
+        BOOST_TEST(test_attr("123456", uint, u));
+        BOOST_TEST(u == 123456);
+
+        BOOST_TEST(test(max_unsigned, uint));
+        BOOST_TEST(test_attr(max_unsigned, uint, u));
+        BOOST_TEST(u == UINT_MAX);
+
+        BOOST_TEST(!test(unsigned_overflow, uint));
+        BOOST_TEST(!test_attr(unsigned_overflow, uint, u));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  binary tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::bin;
+        unsigned u;
+
+        BOOST_TEST(test("11111110", bin));
+        BOOST_TEST(test_attr("11111110", bin, u));
+        BOOST_TEST(u == 0xFE);
+
+        BOOST_TEST(test(max_binary, bin));
+        BOOST_TEST(test_attr(max_binary, bin, u));
+        BOOST_TEST(u == UINT_MAX);
+
+        BOOST_TEST(!test(binary_overflow, bin));
+        BOOST_TEST(!test_attr(binary_overflow, bin, u));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  octal tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::oct;
+        unsigned u;
+
+        BOOST_TEST(test("12545674515", oct));
+        BOOST_TEST(test_attr("12545674515", oct, u));
+        BOOST_TEST(u == 012545674515);
+
+        BOOST_TEST(test(max_octal, oct));
+        BOOST_TEST(test_attr(max_octal, oct, u));
+        BOOST_TEST(u == UINT_MAX);
+
+        BOOST_TEST(!test(octal_overflow, oct));
+        BOOST_TEST(!test_attr(octal_overflow, oct, u));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  hex tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::hex;
+        unsigned u;
+
+        BOOST_TEST(test("95BC8DF", hex));
+        BOOST_TEST(test_attr("95BC8DF", hex, u));
+        BOOST_TEST(u == 0x95BC8DF);
+
+        BOOST_TEST(test("abcdef12", hex));
+        BOOST_TEST(test_attr("abcdef12", hex, u));
+        BOOST_TEST(u == 0xabcdef12);
+
+        BOOST_TEST(test(max_hex, hex));
+        BOOST_TEST(test_attr(max_hex, hex, u));
+        BOOST_TEST(u == UINT_MAX);
+
+        BOOST_TEST(!test(hex_overflow, hex));
+        BOOST_TEST(!test_attr(hex_overflow, hex, u));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  limited fieldwidth
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        unsigned u;
+        using boost::spirit::qi::uint_spec;
+
+        uint_spec<unsigned, 10, 1, 3> uint3;
+        BOOST_TEST(test("123456", uint3, false));
+        BOOST_TEST(test_attr("123456", uint3, u, false));
+        BOOST_TEST(u == 123);
+
+        uint_spec<unsigned, 10, 2, 4> uint4;
+        BOOST_TEST(test("123456", uint4, false));
+        BOOST_TEST(test_attr("123456", uint4, u, false));
+        BOOST_TEST(u == 1234);
+
+        BOOST_TEST(!test("1", uint4));
+        BOOST_TEST(!test_attr("1", uint4, u));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  uint_spec<unused_type> tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using boost::spirit::qi::uint_spec;
+        using boost::spirit::unused_type;
+        uint_spec<unused_type> any_int;
+
+        BOOST_TEST(test("123456", any_int));
+        BOOST_TEST(test("1234567890123456789", any_int));
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    //  action tests
+    ///////////////////////////////////////////////////////////////////////////
+    {
+        using namespace boost::phoenix;
+        using boost::spirit::arg_names::_1;
+        using boost::spirit::ascii::space;
+        using boost::spirit::uint;
+        int n;
+
+        BOOST_TEST(test("123", uint[ref(n) = _1]));
+        BOOST_TEST(n == 123);
+        BOOST_TEST(test("   456", uint[ref(n) = _1], space));
+        BOOST_TEST(n == 456);
+    }
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/support/detail/sstream.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/support/detail/sstream.hpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,46 @@
+/*=============================================================================
+    Copyright (c) 2003 Martin Wille
+    http://spirit.sourceforge.net/
+
+    Use, modification and distribution is subject to the Boost Software
+    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+    http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config.hpp>
+
+///////////////////////////////////////////////////////////////////////////
+// workaround for prestandard support of stringstreams
+//
+// * defines sstream_t for the string stream type
+// * defines std::string getstring(sstream_t &);
+//
+
+#ifdef BOOST_NO_STRINGSTREAM
+#   include <strstream>
+    typedef strstream sstream_t;
+    std::string
+    getstring(std::strstream& ss)
+    {
+        ss << ends;
+        std::string rval = ss.str();
+        ss.freeze(false);
+        return rval;
+    }
+#else
+#   include <sstream>
+    typedef std::stringstream sstream_t;
+    std::string
+    getstring(std::stringstream &ss)
+    {
+        return ss.str();
+    }
+#endif
+
+void use_getstring_to_avoid_compiler_warnings_about_unused_functions()
+{
+    sstream_t ss;
+    getstring(ss);
+    if(!ss) { // to be not recursive on all control paths
+        use_getstring_to_avoid_compiler_warnings_about_unused_functions();
+    }
+}
Added: trunk/libs/spirit/test/support/hold_any.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/support/hold_any.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,201 @@
+//  Copyright (c) 2007-2008 Hartmut Kaiser
+//  Copyright (c) Christopher Diggins 2005 
+//
+//  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)
+
+// #define BOOST_SPIRIT_ANY_IMPLICIT_CASTING
+
+#include <cassert>
+#include <stdexcept>
+#include <typeinfo>
+#include <iostream>
+#include <vector>
+#include <complex>
+#include <string>
+
+#include <boost/detail/lightweight_test.hpp>
+#include <boost/spirit/support/detail/hold_any.hpp>
+
+using namespace std; 
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+bool output_any (hold_any const& a, std::string expected) 
+{
+    std::ostringstream o;
+    if (a.type() == typeid(int)) 
+    {
+        o << any_cast<int>(a);
+    }
+    else if (a.type() == typeid(char)) 
+    {
+        o << any_cast<char>(a);
+    }
+    else if (a.type() == typeid(double)) 
+    {
+        o << any_cast<double>(a);
+    }
+    else if (a.type() == typeid(complex<int>)) 
+    {
+        o << any_cast<complex<int> >(a);
+    }
+    else 
+    {
+        o << "unexpected type: " << a.type().name();
+        return false;
+    }
+    return o.str() == expected;
+}
+
+template <typename T>
+bool output_any_direct (T const& v, std::string expected) 
+{
+    std::ostringstream o;
+    o << v;
+    return o.str() == expected;
+}
+
+void simple_any_test() 
+{
+    BOOST_TEST(output_any(42, "42"));
+    BOOST_TEST(output_any('q', "q"));
+    BOOST_TEST(output_any(3.14, "3.14"));
+    BOOST_TEST(output_any(complex<int>(1, 2), "(1,2)"));
+
+    int n = 42; BOOST_TEST(output_any(n, "42"));
+    char c = 'q'; BOOST_TEST(output_any(c, "q"));
+    double d = 3.14; BOOST_TEST(output_any(d, "3.14"));
+    complex<int> x(1, 2); BOOST_TEST(output_any(x, "(1,2)"));
+  
+    hold_any a;
+    BOOST_TEST(output_any(a = n, "42"));
+    BOOST_TEST(output_any(a = c, "q"));
+    BOOST_TEST(output_any(a = d, "3.14"));  
+    BOOST_TEST(output_any(a = x, "(1,2)"));
+    BOOST_TEST(output_any(a = 13, "13"));
+
+#ifdef BOOST_SPIRIT_ANY_IMPLICIT_CASTING
+    BOOST_TEST(output_any_direct(n = hold_any(42), "42"));
+    BOOST_TEST(output_any_direct(c = hold_any('q'), "q"));
+    BOOST_TEST(output_any_direct(d = hold_any(3.14), "3.14"));  
+    BOOST_TEST(output_any_direct(x = complex<int>(hold_any(complex<int>(1, 2))), "(1,2)"));
+#endif
+  
+    BOOST_TEST(output_any_direct(hold_any(42), "42"));
+    BOOST_TEST(output_any_direct(hold_any('q'), "q"));
+    BOOST_TEST(output_any_direct(hold_any(3.14), "3.14"));  
+    BOOST_TEST(output_any_direct(hold_any(complex<int>(1, 2)), "(1,2)"));
+
+    BOOST_TEST(!a.empty());
+    a = 0;
+    BOOST_TEST(!a.empty());
+    a.reset();
+    BOOST_TEST(a.empty());
+  
+    try {
+        any_cast<int>(a);
+        BOOST_TEST(false);
+    }
+    catch (boost::spirit::bad_any_cast const&) {
+        BOOST_TEST(true);
+    }
+    catch (...) {
+        BOOST_TEST(false);
+    }
+}
+
+void test2(hold_any const& x, hold_any const& y)
+{
+    BOOST_TEST(x.type() != y.type());
+    BOOST_TEST(x.type().name() != y.type().name());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int state; 
+
+///////////////////////////////////////////////////////////////////////////////
+struct small_object 
+{
+    small_object() {}
+    small_object(small_object const& fb) { state = 1; }
+    ~small_object() { state = 2; }
+};
+
+inline std::istream& 
+operator>> (std::istream& i, small_object&)
+{
+    return i;
+}
+
+inline std::ostream& 
+operator<< (std::ostream& o, small_object const&)
+{
+    return o;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct large_object 
+{
+    large_object() {}
+    large_object(large_object const& fb) { state = 3; }
+    ~large_object() { state = 4; }
+    
+    int data0;
+    int data1; 
+    int data2; 
+    int data3;
+};
+
+inline std::istream& 
+operator>> (std::istream& i, large_object&)
+{
+    return i;
+}
+
+inline std::ostream& 
+operator<< (std::ostream& o, large_object const&)
+{
+    return o;
+}
+
+void constructor_test() 
+{
+    small_object lfb;  
+    large_object bfb;  
+    hold_any a;
+    state = 0;
+    
+    a = lfb;  BOOST_TEST(1 == state); state = 0;
+    a = 42;   BOOST_TEST(2 == state); state = 0;
+    a = bfb;  BOOST_TEST(3 == state); state = 0;
+    a = 42;   BOOST_TEST(4 == state); state = 0;
+
+    // test assignment of large objects
+    a = bfb;
+    a = bfb;
+}
+
+int main()
+{  
+    test2(std::string("10"), std::complex<double>(20));
+
+    constructor_test();  
+    simple_any_test();
+
+    hold_any non_const(10);
+    BOOST_TEST(any_cast<int>(non_const) == 10);
+    *any_cast<int>(&non_const) = 15;
+    BOOST_TEST(any_cast<int>(non_const) == 15);
+
+    hold_any const const_(10);
+    BOOST_TEST(any_cast<int>(const_) == *any_cast<int>(&const_));
+
+    hold_any a = 42, b = 'q';
+    swap(a, b);
+    BOOST_TEST(any_cast<int>(b) == 42);
+    BOOST_TEST(any_cast<char>(a) == 'q');
+  
+    return boost::report_errors();
+}
+
Added: trunk/libs/spirit/test/support/multi_pass.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/support/multi_pass.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,770 @@
+/*=============================================================================
+    Copyright (c) 2001-2003 Daniel Nuffer
+    Copyright (c) 2001-2008 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 <boost/spirit/support/iterators/detail/buf_id_check_policy.hpp>
+#include <boost/spirit/support/iterators/detail/ref_counted_policy.hpp>
+#include <boost/spirit/support/iterators/detail/functor_input_policy.hpp>
+#include <boost/spirit/include/support_multi_pass.hpp>
+#include <boost/spirit/support/iterators/look_ahead.hpp>
+
+#include <boost/scoped_ptr.hpp>
+#include <iterator>
+#include <string>
+#include <boost/detail/lightweight_test.hpp>
+#include "detail/sstream.hpp"
+
+using namespace std;
+using namespace boost::spirit;
+
+sstream_t res;
+
+typedef boost::spirit::multi_pass<istream_iterator<char> > default_multi_pass_t;
+
+typedef look_ahead<istream_iterator<char>, 6> fixed_multi_pass_t;
+
+typedef multi_pass<
+    istream_iterator<char>,
+    multi_pass_policies::input_iterator,
+    multi_pass_policies::first_owner,
+    multi_pass_policies::buf_id_check,
+    multi_pass_policies::std_deque
+> first_owner_multi_pass_t;
+
+
+// a functor to test out the functor_multi_pass
+class my_functor
+{
+    public:
+        typedef char result_type;
+        my_functor()
+            : c('A')
+        {}
+
+        char operator()()
+        {
+            if (c == 'M')
+                return eof;
+            else
+                return c++;
+        }
+
+        static result_type eof;
+    private:
+        char c;
+};
+
+my_functor::result_type my_functor::eof = '\0';
+
+typedef multi_pass<
+    my_functor,
+    multi_pass_policies::functor_input,
+    multi_pass_policies::first_owner,
+    multi_pass_policies::no_check,
+    multi_pass_policies::std_deque
+> functor_multi_pass_t;
+
+void test_default_multi_pass()
+{
+    res << "-*= test_default_multi_pass =*-\n";
+    istream_iterator<char> end;
+    boost::scoped_ptr<default_multi_pass_t> mpend(new default_multi_pass_t(end));
+
+    {
+        sstream_t ss;
+        ss << "test string";
+
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a));
+
+        while (*mp1 != *mpend)
+        {
+            res << *((*mp1)++);
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> b(ss);
+        boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b));
+        boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b));
+        *mp3 = *mp2;
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        mp3.reset();
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a));
+        boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(*mp1));
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        while (*mp1 != *mpend)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> b(ss);
+        boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b));
+        boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b));
+        *mp3 = *mp2;
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        mp3.reset();
+        ++*mp2;
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a));
+        boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(*mp1));
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        BOOST_TEST(*mp1 != *mp2);
+        BOOST_TEST(*mp1 > *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp2 < *mp1);
+        BOOST_TEST(*mp2 <= *mp1);
+        while (*mp2 != *mp1)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        while (*mp1 != *mpend)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        BOOST_TEST(*mp1 != *mp2);
+        BOOST_TEST(*mp1 > *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp2 < *mp1);
+        BOOST_TEST(*mp2 <= *mp1);
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<default_multi_pass_t> mp1(new default_multi_pass_t(a));
+        boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(a));
+        BOOST_TEST(*mp1 != *mp2);
+        ++*mp1;
+        BOOST_TEST(*mp1 != *mp2);
+
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> b(ss);
+        boost::scoped_ptr<default_multi_pass_t> mp2(new default_multi_pass_t(b));
+        boost::scoped_ptr<default_multi_pass_t> mp3(new default_multi_pass_t(b));
+        *mp3 = *mp2;
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        mp2->clear_queue();
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        try
+        {
+            res << **mp3; // this should throw illegal_backtracking
+            BOOST_TEST(0);
+        }
+        catch (const boost::spirit::multi_pass_policies::illegal_backtracking& /*e*/)
+        {
+        }
+        res << endl;
+    }
+
+
+}
+
+void test_fixed_multi_pass()
+{
+    res << "-*= test_fixed_multi_pass =*-\n";
+    istream_iterator<char> end;
+    boost::scoped_ptr<fixed_multi_pass_t> mpend(new fixed_multi_pass_t(end));
+
+    {
+        sstream_t ss;
+        ss << "test string";
+
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a));
+
+        while (*mp1 != *mpend)
+        {
+            res << *((*mp1)++);
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> b(ss);
+        boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(b));
+        boost::scoped_ptr<fixed_multi_pass_t> mp3(new fixed_multi_pass_t(*mp2));
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        mp3.reset();
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a));
+        boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(*mp1));
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        while (*mp1 != *mpend)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> b(ss);
+        boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(b));
+        boost::scoped_ptr<fixed_multi_pass_t> mp3(new fixed_multi_pass_t(*mp2));
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        mp3.reset();
+        ++*mp2;
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a));
+        boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(*mp1));
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        BOOST_TEST(*mp1 != *mp2);
+        BOOST_TEST(*mp1 > *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp2 < *mp1);
+        BOOST_TEST(*mp2 <= *mp1);
+        while (*mp2 != *mp1)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        while (*mp1 != *mpend)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        BOOST_TEST(*mp1 != *mp2);
+        BOOST_TEST(*mp1 > *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp2 < *mp1);
+        BOOST_TEST(*mp2 <= *mp1);
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<fixed_multi_pass_t> mp1(new fixed_multi_pass_t(a));
+        boost::scoped_ptr<fixed_multi_pass_t> mp2(new fixed_multi_pass_t(a));
+        BOOST_TEST(*mp1 != *mp2);
+        ++*mp1;
+        BOOST_TEST(*mp1 != *mp2);
+
+    }
+
+}
+
+void test_first_owner_multi_pass()
+{
+    res << "-*= test_first_owner_multi_pass =*-\n";
+    istream_iterator<char> end;
+    boost::scoped_ptr<first_owner_multi_pass_t> mpend(new first_owner_multi_pass_t(end));
+
+    {
+        sstream_t ss;
+        ss << "test string";
+
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a));
+
+        while (*mp1 != *mpend)
+        {
+            res << *((*mp1)++);
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> b(ss);
+        boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b));
+        boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2));
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        mp3.reset();
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a));
+        boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(*mp1));
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        while (*mp1 != *mpend)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> b(ss);
+        boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b));
+        boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2));
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        mp3.reset();
+        ++*mp2;
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a));
+        boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(*mp1));
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        BOOST_TEST(*mp1 != *mp2);
+        BOOST_TEST(*mp1 > *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp2 < *mp1);
+        BOOST_TEST(*mp2 <= *mp1);
+        while (*mp2 != *mp1)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        while (*mp1 != *mpend)
+        {
+            res << **mp1;
+            ++*mp1;
+        }
+
+        BOOST_TEST(*mp1 != *mp2);
+        BOOST_TEST(*mp1 > *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp2 < *mp1);
+        BOOST_TEST(*mp2 <= *mp1);
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        BOOST_TEST(*mp1 == *mp2);
+        BOOST_TEST(*mp1 >= *mp2);
+        BOOST_TEST(*mp1 <= *mp2);
+        res << endl;
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> a(ss);
+        boost::scoped_ptr<first_owner_multi_pass_t> mp1(new first_owner_multi_pass_t(a));
+        boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(a));
+        BOOST_TEST(*mp1 != *mp2);
+        ++*mp1;
+        BOOST_TEST(*mp1 != *mp2);
+
+    }
+
+    {
+        sstream_t ss;
+        ss << "test string";
+        istream_iterator<char> b(ss);
+        boost::scoped_ptr<first_owner_multi_pass_t> mp2(new first_owner_multi_pass_t(b));
+        boost::scoped_ptr<first_owner_multi_pass_t> mp3(new first_owner_multi_pass_t(*mp2));
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        mp2->clear_queue();
+
+        while (*mp2 != *mpend)
+        {
+            res << **mp2;
+            ++*mp2;
+        }
+
+        try
+        {
+            res << **mp3; // this should throw illegal_backtracking
+            BOOST_TEST(0);
+        }
+        catch (const boost::spirit::multi_pass_policies::illegal_backtracking& /*e*/)
+        {
+        }
+        res << endl;
+    }
+
+}
+
+
+void test_functor_multi_pass()
+{
+    res << "-*= test_functor_multi_pass =*-\n";
+    functor_multi_pass_t mpend;
+
+    {
+        functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());
+
+        while (mp1 != mpend)
+        {
+            res << *(mp1++);
+        }
+
+        res << endl;
+    }
+
+    {
+        functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());
+        functor_multi_pass_t mp2 = functor_multi_pass_t(mp1);
+
+        for (int i = 0; i < 4; ++i)
+        {
+            res << *mp1;
+            ++mp1;
+        }
+
+        while (mp2 != mpend)
+        {
+            res << *mp2;
+            ++mp2;
+        }
+
+        while (mp1 != mpend)
+        {
+            res << *mp1;
+            ++mp1;
+        }
+
+        res << endl;
+    }
+
+    {
+        functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());
+        functor_multi_pass_t mp2 = functor_multi_pass_t(mp1);
+
+        BOOST_TEST(mp1 == mp2);
+        BOOST_TEST(mp1 >= mp2);
+        BOOST_TEST(mp1 <= mp2);
+        for (int i = 0; i < 4; ++i)
+        {
+            res << *mp1;
+            ++mp1;
+        }
+
+        BOOST_TEST(mp1 != mp2);
+        BOOST_TEST(mp1 > mp2);
+        BOOST_TEST(mp1 >= mp2);
+        BOOST_TEST(mp2 < mp1);
+        BOOST_TEST(mp2 <= mp1);
+        while (mp2 != mp1)
+        {
+            res << *mp2;
+            ++mp2;
+        }
+
+        BOOST_TEST(mp1 == mp2);
+        BOOST_TEST(mp1 >= mp2);
+        BOOST_TEST(mp1 <= mp2);
+        while (mp1 != mpend)
+        {
+            res << *mp1;
+            ++mp1;
+        }
+
+        BOOST_TEST(mp1 != mp2);
+        BOOST_TEST(mp1 > mp2);
+        BOOST_TEST(mp1 >= mp2);
+        BOOST_TEST(mp2 < mp1);
+        BOOST_TEST(mp2 <= mp1);
+        while (mp2 != mpend)
+        {
+            res << *mp2;
+            ++mp2;
+        }
+
+        BOOST_TEST(mp1 == mp2);
+        BOOST_TEST(mp1 >= mp2);
+        BOOST_TEST(mp1 <= mp2);
+        res << endl;
+    }
+
+    {
+        functor_multi_pass_t mp1 = functor_multi_pass_t(my_functor());
+        functor_multi_pass_t mp2 = functor_multi_pass_t(my_functor());
+        BOOST_TEST(mp1 != mp2);
+        ++mp1;
+        BOOST_TEST(mp1 != mp2);
+
+    }
+}
+
+int main(int, char**)
+{
+
+    test_default_multi_pass();
+    test_fixed_multi_pass();
+    test_first_owner_multi_pass();
+    test_functor_multi_pass();
+
+    BOOST_TEST(getstring(res) == "-*= test_default_multi_pass =*-\n"
+            "teststring\n"
+            "teststring\n"
+            "testteststringstring\n"
+            "testtring\n"
+            "testteststringstring\n"
+            "teststring\n"
+            "-*= test_fixed_multi_pass =*-\n"
+            "teststring\n"
+            "teststring\n"
+            "testteststringstring\n"
+            "testtring\n"
+            "testteststringstring\n"
+            "-*= test_first_owner_multi_pass =*-\n"
+            "teststring\n"
+            "teststring\n"
+            "testteststringstring\n"
+            "testtring\n"
+            "testteststringstring\n"
+            "teststring\n"
+            "-*= test_functor_multi_pass =*-\n"
+            "ABCDEFGHIJKL\n"
+            "ABCDABCDEFGHIJKLEFGHIJKL\n"
+            "ABCDABCDEFGHIJKLEFGHIJKL\n");
+
+    return boost::report_errors();
+}
Added: trunk/libs/spirit/test/support/multi_pass_compile.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/test/support/multi_pass_compile.cpp	2008-04-12 23:02:30 EDT (Sat, 12 Apr 2008)
@@ -0,0 +1,63 @@
+/*=============================================================================
+    Copyright (c) 2004-2008 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 is a compile only test for verifying, whether the multi_pass<>
+//  iterator works ok with an input iterator, which returns a value_type and not
+//  a reference from its dereferencing operator.
+
+#include <cstdio>
+#include <fstream>
+#include <iterator>
+#include <boost/detail/lightweight_test.hpp>
+
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_numeric.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+#include <boost/spirit/include/qi_nonterminal.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+#include <boost/spirit/include/support_multi_pass.hpp>
+
+#if defined(BOOST_HAS_UNISTD_H)
+#include <unistd.h>    // unlink()
+#endif
+
+#if defined(__MINGW32__)
+#include <io.h>    // unlink()
+#endif
+
+using namespace boost::spirit;
+using namespace boost::spirit::qi;
+using namespace std;
+
+int main ()
+{
+    // create a sample file
+    {
+        ofstream out("./input_file.txt");
+        out << 1.0 << "," << 2.0;
+    }
+
+    // read in the values from the sample file
+    {
+        ifstream in("./input_file.txt"); // we get our input from this file
+
+        typedef multi_pass<istreambuf_iterator<char> > iterator_type;
+
+        iterator_type first(make_multi_pass(istreambuf_iterator<char>(in)));
+        iterator_type last(make_multi_pass(istreambuf_iterator<char>()));
+
+        rule<iterator_type> n_list; 
+        n_list = double_ >> *(char_(',') >> double_);
+        BOOST_TEST(parse(first, last, n_list));
+    }
+
+#if !defined(__COMO_VERSION__)
+    unlink("./input_file.txt");
+#endif
+
+    return boost::report_errors();
+}