|
Boost-Commit : |
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();
+}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk