Boost logo

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'''&ouml;'''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 &nbsp;<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">&lt;</span><span class="keyword">typename</span> <span class="identifier">Eval</span><span class="special">&gt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">&gt;</span>
+ <span class="identifier">return_type</span>
+ <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&amp;</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">&lt;</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">&gt;</span>
+ <span class="identifier">return_type</span>
+ <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&amp;</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&amp;</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">&lt;</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">&gt;</span>
+</pre>
+<p>
+ The algorithm module provides wrappers for the standard algorithms in the
+ <tt class="computeroutput"><span class="special">&lt;</span><span class="identifier">algorithm</span><span class="special">&gt;</span></tt> and <tt class="computeroutput"><span class="special">&lt;</span><span class="identifier">numeric</span><span class="special">&gt;</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">&lt;</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">&gt;</span>
+<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
+<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</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">&lt;</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">&gt;</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">&amp;&amp;</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">// &lt;--- 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">&lt;&lt;</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">&lt;&lt;</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">&lt;&lt;</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">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">A1</span><span class="special">,</span> <span class="special">...</span> <span class="identifier">AN</span><span class="special">&gt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">Arg</span><span class="special">&gt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">Arg</span><span class="special">&gt;</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">&lt;=</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">-&gt;</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">&lt;</span><span class="identifier">factorial_impl</span><span class="special">&gt;</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">&lt;&lt;</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">&lt;</span><span class="identifier">factorial_impl</span><span class="special">&gt;</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">&lt;</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">&lt;&lt;</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">-&gt;*</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">-&gt;*</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">&lt;&lt;</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">&lt;&lt;</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">&amp;</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">&amp;=,</span> <span class="special">|=,</span> <span class="special">^=,</span> <span class="special">&lt;&lt;=,</span> <span class="special">&gt;&gt;=</span>
+<span class="special">+,</span> <span class="special">-,</span> <span class="special">*,</span> <span class="special">/,</span> <span class="special">%,</span> <span class="special">&amp;,</span> <span class="special">|,</span> <span class="special">^,</span> <span class="special">&lt;&lt;,</span> <span class="special">&gt;&gt;</span>
+<span class="special">==,</span> <span class="special">!=,</span> <span class="special">&lt;,</span> <span class="special">&gt;,</span> <span class="special">&lt;=,</span> <span class="special">&gt;=</span>
+<span class="special">&amp;&amp;,</span> <span class="special">||,</span> <span class="special">-&gt;*</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">-&gt;*</span><span class="identifier">member_object_pointer</span>
+<span class="identifier">a</span><span class="special">-&gt;*</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">-&gt;*&amp;</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-&gt;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">-&gt;*&amp;</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-&gt;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">&lt;</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">&gt;</span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">&amp;=</span></tt>, <tt class="computeroutput"><span class="special">|=</span></tt>, <tt class="computeroutput"><span class="special">^=</span></tt>,
+ <tt class="computeroutput"><span class="special">&lt;&lt;=</span></tt>, <tt class="computeroutput"><span class="special">&gt;&gt;=</span></tt>, <tt class="computeroutput"><span class="special">&amp;</span></tt>,
+ <tt class="computeroutput"><span class="special">|</span></tt>, <tt class="computeroutput"><span class="special">^</span></tt>,
+ <tt class="computeroutput"><span class="special">&lt;&lt;</span></tt>, <tt class="computeroutput"><span class="special">&gt;&gt;</span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</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">&lt;</span></tt>,
+ <tt class="computeroutput"><span class="special">&lt;=</span></tt>, <tt class="computeroutput"><span class="special">&gt;</span></tt>,
+ <tt class="computeroutput"><span class="special">&gt;=</span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">&lt;&lt;</span></tt>, <tt class="computeroutput"><span class="special">&gt;&gt;</span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">!</span></tt>, &amp;&amp;,
+ <tt class="computeroutput"><span class="special">||</span></tt>
+</td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span></tt></td>
+</tr>
+<tr>
+<td>
+<tt class="computeroutput"><span class="special">&amp;</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">&lt;</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">&gt;</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">&lt;</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">&gt;</span></tt></td>
+</tr>
+<tr>
+<td><tt class="computeroutput"><span class="special">-&gt;*</span></tt></td>
+<td><tt class="computeroutput"><span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</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">&lt;&lt;</span> <span class="identifier">arg1</span> <span class="special">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;</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">&gt;</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">&lt;</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">&gt;</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">" &gt; 5"</span></tt>, <tt class="computeroutput"><span class="string">"
+ == 5"</span></tt> or <tt class="computeroutput"><span class="string">" &lt; 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">&gt;</span> <span class="number">5</span><span class="special">)</span>
+ <span class="special">[</span>
+ <span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">arg1</span> <span class="special">&lt;&lt;</span> <span class="string">" &gt; 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">&lt;&lt;</span> <span class="identifier">arg1</span> <span class="special">&lt;&lt;</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">&lt;&lt;</span> <span class="identifier">arg1</span> <span class="special">&lt;&lt;</span> <span class="string">" &lt; 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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">integral_value</span><span class="special">&gt;(</span><span class="identifier">sequenced_statements</span><span class="special">),</span>
+ <span class="special">...</span>
+ <span class="identifier">default_</span><span class="special">&lt;</span><span class="identifier">integral_value</span><span class="special">&gt;(</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">&lt;</span><span class="number">1</span><span class="special">&gt;(</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"one"</span><span class="special">)</span> <span class="special">&lt;&lt;</span> <span class="char">'\n'</span><span class="special">),</span>
+ <span class="identifier">case_</span><span class="special">&lt;</span><span class="number">2</span><span class="special">&gt;(</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"two"</span><span class="special">)</span> <span class="special">&lt;&lt;</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">&lt;&lt;</span> <span class="identifier">val</span><span class="special">(</span><span class="string">"other value"</span><span class="special">)</span> <span class="special">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;&lt;</span> <span class="identifier">arg1</span> <span class="special">&lt;&lt;</span> <span class="string">", "</span>
+ <span class="special">],</span>
+ <span class="identifier">cout</span> <span class="special">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;&lt;</span> <span class="identifier">arg1</span> <span class="special">&lt;&lt;</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">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;</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">&lt;&lt;</span> <span class="identifier">arg1</span> <span class="special">&lt;&lt;</span> <span class="string">", "</span>
+ <span class="special">],</span>
+ <span class="identifier">cout</span> <span class="special">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">exception_type</span><span class="special">&gt;()</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">&lt;</span><span class="identifier">runtime_error</span><span class="special">&gt;()</span>
+<span class="special">[</span>
+ <span class="identifier">cout</span> <span class="special">&lt;&lt;</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">&lt;</span><span class="identifier">exception</span><span class="special">&gt;()</span>
+<span class="special">[</span>
+ <span class="identifier">cout</span> <span class="special">&lt;&lt;</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">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">runtime_error</span><span class="special">&gt;()</span>
+<span class="special">[</span>
+ <span class="identifier">cout</span> <span class="special">&lt;&lt;</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">&lt;</span><span class="identifier">exception</span><span class="special">&gt;()</span>
+<span class="special">[</span>
+ <span class="identifier">cout</span> <span class="special">&lt;&lt;</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">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</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">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</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">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</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">&lt;</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">&gt;</span>
+<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
+<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</span>
+<span class="preprocessor">#include</span> <span class="special">&lt;</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">&gt;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">lambda_expression</span><span class="special">)</span>
+<span class="identifier">dynamic_cast_</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">lambda_expression</span><span class="special">)</span>
+<span class="identifier">const_cast_</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</span><span class="identifier">lambda_expression</span><span class="special">)</span>
+<span class="identifier">reinterpret_cast_</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</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">&lt;</span><span class="identifier">Base</span><span class="special">*&gt;(&amp;</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">&lt;</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">&gt;</span>
+</pre>
+<p>
+ We use an instance of:
+ </p>
+<pre class="programlisting">
+<span class="identifier">actor</span><span class="special">&lt;</span><span class="identifier">local_variable</span><span class="special">&lt;</span><span class="identifier">Key</span><span class="special">&gt;</span> <span class="special">&gt;</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">&lt;</span><span class="identifier">local_variable</span><span class="special">&lt;</span><span class="identifier">size_key</span><span class="special">&gt;</span> <span class="special">&gt;</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">&lt;</span><span class="identifier">local_variable</span><span class="special">&lt;</span><span class="identifier">Key</span><span class="special">&gt;</span> <span class="special">&gt;</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">&lt;</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">&gt;</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">&lt;&lt;</span> <span class="special">--</span><span class="identifier">_a</span> <span class="special">&lt;&lt;</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">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</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">&lt;&lt;</span> <span class="special">--</span><span class="identifier">_a</span> <span class="special">&lt;&lt;</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">&lt;&lt;</span> <span class="identifier">i</span> <span class="special">&lt;&lt;</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">&lt;&lt;</span> <span class="identifier">_x</span> <span class="special">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;</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">&gt;</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">&lt;</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">&gt;</span>
+ <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">C</span><span class="special">&amp;</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">&lt;</span><span class="identifier">for_each_impl</span><span class="special">&gt;</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">&lt;&lt;</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">&lt;</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">&gt;</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">&lt;</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">&gt;</span>
+ <span class="keyword">void</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">C</span><span class="special">&amp;</span> <span class="identifier">c</span><span class="special">,</span> <span class="identifier">T</span><span class="special">&amp;</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">&lt;</span><span class="identifier">push_back_impl</span><span class="special">&gt;</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">&lt;</span><span class="identifier">vector</span><span class="special">&lt;</span><span class="keyword">int</span><span class="special">&gt;</span> <span class="special">&gt;</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">&lt;</span><span class="keyword">int</span><span class="special">&gt;</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">&lt;</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">&gt;</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">&lt;&lt;</span> <span class="identifier">n</span> <span class="special">&lt;&lt;</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">(&amp;</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">(&amp;</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">&lt;</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">&gt;</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">(&amp;</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">(&amp;</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">(&amp;</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">(&amp;</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">&lt;</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">&gt;</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">(&amp;</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">(&amp;</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">(&amp;</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">(&amp;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">Eval</span><span class="special">&gt;</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">&amp;</span> <span class="identifier">base</span><span class="special">);</span>
+
+ <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">&gt;</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">&amp;</span> <span class="identifier">_0</span><span class="special">);</span>
+
+ <span class="keyword">template</span> <span class="special">&lt;</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">&gt;</span>
+ <span class="identifier">actor</span><span class="special">(</span><span class="identifier">T0</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">T1</span> <span class="keyword">const</span><span class="special">&amp;</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">&lt;</span><span class="identifier">eval_type</span><span class="special">,</span> <span class="identifier">basic_environment</span><span class="special">&lt;&gt;</span> <span class="special">&gt;::</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">T0</span><span class="special">&gt;</span>
+ <span class="keyword">typename</span> <span class="identifier">apply_actor</span><span class="special">&lt;</span><span class="identifier">eval_type</span><span class="special">,</span> <span class="identifier">basic_environment</span><span class="special">&lt;</span><span class="identifier">T0</span><span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">type</span>
+ <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&amp;</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">&lt;</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">&gt;</span>
+ <span class="keyword">typename</span> <span class="identifier">apply_actor</span><span class="special">&lt;</span><span class="identifier">eval_type</span><span class="special">,</span> <span class="identifier">basic_environment</span><span class="special">&lt;</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">type</span>
+ <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&amp;</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&amp;</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">&lt;</span><span class="identifier">Env</span><span class="special">&gt;::</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">Env</span><span class="special">&gt;::</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">&gt;</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">&lt;</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">&gt;</span>
+<span class="keyword">typename</span> <span class="identifier">apply_actor</span><span class="special">&lt;</span><span class="identifier">eval_type</span><span class="special">,</span> <span class="identifier">basic_environment</span><span class="special">&lt;</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&gt;</span> <span class="special">&gt;::</span><span class="identifier">type</span>
+<span class="keyword">operator</span><span class="special">()(</span><span class="identifier">T0</span><span class="special">&amp;</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&amp;</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">&lt;</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&gt;(</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">&lt;</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">&gt;</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">&lt;</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">&gt;</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">&lt;</span><span class="identifier">env_type</span><span class="special">&gt;::</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
+<span class="keyword">struct</span> <span class="identifier">reference</span>
+<span class="special">{</span>
+ <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">&gt;</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">&amp;</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">&amp;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">&gt;</span>
+ <span class="identifier">T</span><span class="special">&amp;</span> <span class="identifier">eval</span><span class="special">(</span><span class="identifier">Env</span> <span class="keyword">const</span><span class="special">&amp;)</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">&amp;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">T</span><span class="special">&gt;</span>
+<span class="identifier">actor</span><span class="special">&lt;</span><span class="identifier">reference</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;</span> <span class="special">&gt;</span> <span class="keyword">const</span>
+<span class="identifier">ref</span><span class="special">(</span><span class="identifier">T</span><span class="special">&amp;</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;(</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">&lt;</span><span class="identifier">T</span><span class="special">&gt;</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">&lt;</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">&gt;</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">&gt;</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">&amp;</span> <span class="identifier">actors</span><span class="special">);</span>
+
+ <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">U0</span><span class="special">&gt;</span>
+ <span class="identifier">composite</span><span class="special">(</span><span class="identifier">U0</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">_0</span><span class="special">);</span>
+
+ <span class="keyword">template</span> <span class="special">&lt;</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">&gt;</span>
+ <span class="identifier">composite</span><span class="special">(</span><span class="identifier">U0</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">_0</span><span class="special">,</span> <span class="identifier">U1</span> <span class="keyword">const</span><span class="special">&amp;</span> <span class="identifier">_1</span><span class="special">);</span>
+
+ <span class="comment">// more constructors
+</span>
+ <span class="keyword">template</span> <span class="special">&lt;</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">&gt;</span>
+ <span class="keyword">typename</span> <span class="identifier">result</span><span class="special">&lt;</span><span class="identifier">Env</span><span class="special">&gt;::</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">&amp;</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">&lt;</span><span class="identifier">RT</span><span class="special">&gt;(</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">&lt;</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">&gt;::</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">&lt;</span><span class="keyword">typename</span> <span class="identifier">Env</span><span class="special">&gt;</span>
+<span class="keyword">typename</span> <span class="identifier">result</span><span class="special">&lt;</span><span class="identifier">Env</span><span class="special">&gt;::</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">&amp;</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">&lt;</span><span class="identifier">Env</span><span class="special">&gt;::</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">&lt;</span><span class="identifier">return_type</span><span class="special">&gt;(</span>
+ <span class="identifier">env</span>
+ <span class="special">,</span> <span class="identifier">get</span><span class="special">&lt;</span><span class="number">0</span><span class="special">&gt;(*</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">&lt;</span><span class="number">1</span><span class="special">&gt;(*</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">&lt;</span><span class="identifier">EvalPolicy</span><span class="special">&gt;(</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