summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/spirit/example
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/spirit/example
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/spirit/example')
-rw-r--r--src/boost/libs/spirit/example/Jamfile20
-rw-r--r--src/boost/libs/spirit/example/karma/Jamfile38
-rw-r--r--src/boost/libs/spirit/example/karma/actions.cpp131
-rw-r--r--src/boost/libs/spirit/example/karma/auto_facilities.cpp244
-rw-r--r--src/boost/libs/spirit/example/karma/basic_facilities.cpp229
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast.hpp177
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast_dump.cpp170
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast_rpn.cpp172
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast_vm.cpp248
-rw-r--r--src/boost/libs/spirit/example/karma/calc2_ast_vm.hpp190
-rw-r--r--src/boost/libs/spirit/example/karma/classify_char.cpp103
-rw-r--r--src/boost/libs/spirit/example/karma/complex_number.cpp132
-rw-r--r--src/boost/libs/spirit/example/karma/complex_number_adapt.cpp153
-rw-r--r--src/boost/libs/spirit/example/karma/complex_number_easier.cpp133
-rw-r--r--src/boost/libs/spirit/example/karma/customize_counter.cpp127
-rw-r--r--src/boost/libs/spirit/example/karma/customize_embedded_container.cpp108
-rw-r--r--src/boost/libs/spirit/example/karma/customize_use_as_container.cpp164
-rw-r--r--src/boost/libs/spirit/example/karma/escaped_string.cpp66
-rw-r--r--src/boost/libs/spirit/example/karma/generate_code.cpp80
-rw-r--r--src/boost/libs/spirit/example/karma/key_value_sequence.cpp74
-rw-r--r--src/boost/libs/spirit/example/karma/mini_xml_karma.cpp222
-rw-r--r--src/boost/libs/spirit/example/karma/num_list1.cpp121
-rw-r--r--src/boost/libs/spirit/example/karma/num_list2.cpp117
-rw-r--r--src/boost/libs/spirit/example/karma/num_list3.cpp150
-rw-r--r--src/boost/libs/spirit/example/karma/num_matrix.cpp114
-rw-r--r--src/boost/libs/spirit/example/karma/printf_style_double_format.cpp282
-rw-r--r--src/boost/libs/spirit/example/karma/quick_start1.cpp119
-rw-r--r--src/boost/libs/spirit/example/karma/quoted_strings.cpp70
-rw-r--r--src/boost/libs/spirit/example/karma/reference.cpp911
-rw-r--r--src/boost/libs/spirit/example/karma/reorder_struct.cpp105
-rw-r--r--src/boost/libs/spirit/example/karma/simple_columns_directive.cpp49
-rw-r--r--src/boost/libs/spirit/example/karma/simple_columns_directive.hpp133
-rw-r--r--src/boost/libs/spirit/example/lex/Jamfile32
-rw-r--r--src/boost/libs/spirit/example/lex/custom_token_attribute.cpp112
-rw-r--r--src/boost/libs/spirit/example/lex/example.hpp26
-rw-r--r--src/boost/libs/spirit/example/lex/example1.cpp133
-rw-r--r--src/boost/libs/spirit/example/lex/example1.input5
-rw-r--r--src/boost/libs/spirit/example/lex/example2.cpp169
-rw-r--r--src/boost/libs/spirit/example/lex/example2.input7
-rw-r--r--src/boost/libs/spirit/example/lex/example3.cpp150
-rw-r--r--src/boost/libs/spirit/example/lex/example3.input5
-rw-r--r--src/boost/libs/spirit/example/lex/example4.cpp227
-rw-r--r--src/boost/libs/spirit/example/lex/example4.input17
-rw-r--r--src/boost/libs/spirit/example/lex/example5.cpp273
-rw-r--r--src/boost/libs/spirit/example/lex/example5.input16
-rw-r--r--src/boost/libs/spirit/example/lex/example6.cpp249
-rw-r--r--src/boost/libs/spirit/example/lex/example6.input17
-rw-r--r--src/boost/libs/spirit/example/lex/lexer_debug_support.cpp109
-rw-r--r--src/boost/libs/spirit/example/lex/print_number_tokenids.cpp121
-rw-r--r--src/boost/libs/spirit/example/lex/print_numbers.cpp118
-rw-r--r--src/boost/libs/spirit/example/lex/print_numbers.input17
-rw-r--r--src/boost/libs/spirit/example/lex/reference.cpp30
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/Jamfile15
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count.input7
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count_generate.cpp45
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_generate.cpp45
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_static.cpp84
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_static.hpp164
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_tokens.hpp62
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count_static.cpp120
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count_static.hpp164
-rw-r--r--src/boost/libs/spirit/example/lex/static_lexer/word_count_tokens.hpp41
-rw-r--r--src/boost/libs/spirit/example/lex/strip_comments.cpp163
-rw-r--r--src/boost/libs/spirit/example/lex/strip_comments.input162
-rw-r--r--src/boost/libs/spirit/example/lex/strip_comments_lexer.cpp172
-rw-r--r--src/boost/libs/spirit/example/lex/word_count.cpp166
-rw-r--r--src/boost/libs/spirit/example/lex/word_count.input7
-rw-r--r--src/boost/libs/spirit/example/lex/word_count_functor.cpp183
-rw-r--r--src/boost/libs/spirit/example/lex/word_count_functor.flex59
-rw-r--r--src/boost/libs/spirit/example/lex/word_count_functor_flex.cpp1576
-rw-r--r--src/boost/libs/spirit/example/lex/word_count_lexer.cpp152
-rw-r--r--src/boost/libs/spirit/example/qi/Jamfile48
-rw-r--r--src/boost/libs/spirit/example/qi/actions.cpp108
-rw-r--r--src/boost/libs/spirit/example/qi/adapt_template_struct.cpp92
-rw-r--r--src/boost/libs/spirit/example/qi/boost_array.cpp119
-rw-r--r--src/boost/libs/spirit/example/qi/calc_utree.cpp166
-rw-r--r--src/boost/libs/spirit/example/qi/calc_utree_ast.cpp164
-rw-r--r--src/boost/libs/spirit/example/qi/calc_utree_naive.cpp134
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/Jamfile132
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc1.cpp118
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp131
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc3.cpp124
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc4.cpp285
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc5.cpp339
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc6.cpp373
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp78
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp117
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp222
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp85
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp93
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp53
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp94
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp101
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp32
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp75
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.cpp66
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp52
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/annotation.hpp78
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/ast.hpp172
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp382
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.hpp92
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/error_handler.hpp93
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.hpp68
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression_def.hpp159
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/main.cpp97
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.hpp37
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement_def.hpp111
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp163
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.hpp77
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/annotation.hpp95
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/ast.hpp275
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.cpp628
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.hpp123
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/error_handler.hpp93
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.hpp75
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression_def.hpp131
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.hpp32
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function_def.hpp71
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/main.cpp121
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/skipper.hpp40
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.hpp38
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement_def.hpp128
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.cpp159
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.hpp82
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/annotation.hpp95
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ast.hpp209
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.cpp622
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.hpp123
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/config.hpp51
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer.hpp483
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer_generate.cpp43
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_switch_lexer.hpp873
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/error_handler.hpp105
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.hpp58
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression_def.hpp94
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.hpp36
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function_def.hpp64
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ids.hpp154
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.cpp17
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.hpp128
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer_def.hpp74
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/main.cpp131
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.hpp42
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement_def.hpp123
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.cpp160
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.hpp82
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp141
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp240
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp1141
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp311
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp51
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp483
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp43
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp873
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp99
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp59
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp104
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp36
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp64
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp160
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp17
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp144
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp100
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp156
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp20
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp42
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp126
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp43
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp121
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/error.cnj16
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/factorial.cnj15
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/operators.cnj137
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/pow2.cnj19
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/precedence.cnj8
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/annotation.hpp95
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/ast.hpp225
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.cpp538
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.hpp118
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/error_handler.hpp93
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.hpp79
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression_def.hpp181
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.hpp32
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function_def.hpp71
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/main.cpp121
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/skipper.hpp40
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.cpp14
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.hpp38
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement_def.hpp124
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.cpp159
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.hpp82
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/1.mini19
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/2.mini15
-rw-r--r--src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/3.mini17
-rw-r--r--src/boost/libs/spirit/example/qi/complex_number.cpp101
-rw-r--r--src/boost/libs/spirit/example/qi/custom_string.cpp113
-rw-r--r--src/boost/libs/spirit/example/qi/display_attribute_type.cpp22
-rw-r--r--src/boost/libs/spirit/example/qi/display_attribute_type.hpp59
-rw-r--r--src/boost/libs/spirit/example/qi/employee.cpp151
-rw-r--r--src/boost/libs/spirit/example/qi/expect.cpp112
-rw-r--r--src/boost/libs/spirit/example/qi/german_floating_point.cpp48
-rw-r--r--src/boost/libs/spirit/example/qi/iter_pos.hpp83
-rw-r--r--src/boost/libs/spirit/example/qi/iter_pos_parser.cpp51
-rw-r--r--src/boost/libs/spirit/example/qi/key_value_sequence.cpp78
-rw-r--r--src/boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp83
-rw-r--r--src/boost/libs/spirit/example/qi/key_value_sequence_ordered.cpp78
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml1.cpp242
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml2.cpp237
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml3.cpp258
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml_samples/1.toyxml1
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml_samples/2.toyxml1
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml_samples/3.toyxml5
-rw-r--r--src/boost/libs/spirit/example/qi/mini_xml_samples/4.toyxml1
-rw-r--r--src/boost/libs/spirit/example/qi/nabialek.cpp98
-rw-r--r--src/boost/libs/spirit/example/qi/num_list1.cpp90
-rw-r--r--src/boost/libs/spirit/example/qi/num_list2.cpp109
-rw-r--r--src/boost/libs/spirit/example/qi/num_list3.cpp108
-rw-r--r--src/boost/libs/spirit/example/qi/num_list4.cpp106
-rw-r--r--src/boost/libs/spirit/example/qi/parse_date.cpp125
-rw-r--r--src/boost/libs/spirit/example/qi/porting_guide_classic.cpp108
-rw-r--r--src/boost/libs/spirit/example/qi/porting_guide_qi.cpp106
-rw-r--r--src/boost/libs/spirit/example/qi/reference.cpp1481
-rw-r--r--src/boost/libs/spirit/example/qi/reorder_struct.cpp130
-rw-r--r--src/boost/libs/spirit/example/qi/roman.cpp188
-rw-r--r--src/boost/libs/spirit/example/qi/sum.cpp106
-rw-r--r--src/boost/libs/spirit/example/qi/typeof.cpp65
-rw-r--r--src/boost/libs/spirit/example/qi/unescaped_string.cpp72
-rw-r--r--src/boost/libs/spirit/example/support/Jamfile16
-rw-r--r--src/boost/libs/spirit/example/support/multi_pass.cpp50
-rw-r--r--src/boost/libs/spirit/example/support/multi_pass.txt6
-rw-r--r--src/boost/libs/spirit/example/support/utree/error_handler.hpp112
-rw-r--r--src/boost/libs/spirit/example/support/utree/parse_sexpr.cpp62
-rw-r--r--src/boost/libs/spirit/example/support/utree/sexpr_generator.hpp128
-rw-r--r--src/boost/libs/spirit/example/support/utree/sexpr_parser.hpp250
-rw-r--r--src/boost/libs/spirit/example/support/utree/utf8_parser.hpp138
-rw-r--r--src/boost/libs/spirit/example/x3/Jamfile65
-rw-r--r--src/boost/libs/spirit/example/x3/actions.cpp52
-rw-r--r--src/boost/libs/spirit/example/x3/annotation.cpp246
-rw-r--r--src/boost/libs/spirit/example/x3/attributes/tuple.cpp51
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc1.cpp123
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc2.cpp139
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc4.cpp273
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc4b.cpp273
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc4c/calc4c.cpp77
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc4c/grammar.cpp68
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc4c/grammar.hpp192
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc5.cpp301
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc6.cpp341
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/ast.hpp63
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/ast_adapted.hpp25
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/compiler.cpp55
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/compiler.hpp33
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/error_handler.hpp40
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/expression.cpp15
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/expression.hpp26
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/expression_def.hpp71
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/main.cpp81
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/vm.cpp50
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc7/vm.hpp48
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/ast.hpp98
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/ast_adapted.hpp33
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/common.hpp28
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/compiler.cpp217
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/compiler.hpp80
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/config.hpp26
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/error_handler.hpp44
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/expression.cpp13
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/expression.hpp26
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/expression_def.hpp91
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/main.cpp114
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/statement.cpp13
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/statement.hpp26
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/statement_def.hpp84
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/vm.cpp64
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc8/vm.hpp51
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/ast.hpp139
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/ast_adapted.hpp41
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/common.hpp28
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/compiler.cpp376
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/compiler.hpp87
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/config.hpp26
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/error_handler.hpp44
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/expression.cpp13
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/expression.hpp26
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/expression_def.hpp182
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/main.cpp110
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/statement.cpp13
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/statement.hpp27
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/statement_def.hpp84
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/vm.cpp156
-rw-r--r--src/boost/libs/spirit/example/x3/calc/calc9/vm.hpp81
-rw-r--r--src/boost/libs/spirit/example/x3/complex_number.cpp98
-rw-r--r--src/boost/libs/spirit/example/x3/employee.cpp134
-rw-r--r--src/boost/libs/spirit/example/x3/error_handling.cpp277
-rw-r--r--src/boost/libs/spirit/example/x3/minimal/ast.hpp31
-rw-r--r--src/boost/libs/spirit/example/x3/minimal/ast_adapted.hpp21
-rw-r--r--src/boost/libs/spirit/example/x3/minimal/config.hpp20
-rw-r--r--src/boost/libs/spirit/example/x3/minimal/employee.cpp13
-rw-r--r--src/boost/libs/spirit/example/x3/minimal/employee.hpp30
-rw-r--r--src/boost/libs/spirit/example/x3/minimal/employee_def.hpp56
-rw-r--r--src/boost/libs/spirit/example/x3/minimal/main.cpp79
-rw-r--r--src/boost/libs/spirit/example/x3/num_list/num_list1.cpp87
-rw-r--r--src/boost/libs/spirit/example/x3/num_list/num_list2.cpp101
-rw-r--r--src/boost/libs/spirit/example/x3/num_list/num_list3.cpp101
-rw-r--r--src/boost/libs/spirit/example/x3/num_list/num_list4.cpp103
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_examples/a.rexpr8
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/Jamfile20
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/ast.hpp42
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/ast_adapted.hpp22
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/config.hpp35
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/error_handler.hpp72
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/printer.hpp57
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/rexpr.hpp33
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/rexpr_def.hpp94
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/src/rexpr.cpp14
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/Jamfile23
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/parse_rexpr_test.cpp86
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/a.expect8
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/a.input8
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/b.expect4
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/b.input8
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/c.expect4
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/c.input8
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/d.expect4
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/d.input8
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/e.expect5
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/e.input8
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/testing.hpp269
-rw-r--r--src/boost/libs/spirit/example/x3/rexpr/rexpr_min/rexpr.cpp215
-rw-r--r--src/boost/libs/spirit/example/x3/roman.cpp179
-rw-r--r--src/boost/libs/spirit/example/x3/sum.cpp98
344 files changed, 41226 insertions, 0 deletions
diff --git a/src/boost/libs/spirit/example/Jamfile b/src/boost/libs/spirit/example/Jamfile
new file mode 100644
index 00000000..4aa2c3dd
--- /dev/null
+++ b/src/boost/libs/spirit/example/Jamfile
@@ -0,0 +1,20 @@
+#==============================================================================
+# Copyright (c) 2010 Gevorg Voskanyan
+# Copyright (c) 2001-2010 Joel de Guzman
+# Copyright (c) 2001-2010 Hartmut Kaiser
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+
+# build all examples
+
+local examples = [ glob-tree [jJ]amfile [jJ]amfile.v2 ] ;
+
+for local ex in $(examples) {
+ local dir = $(ex:P) ;
+ if $(dir) != "" && $(dir) != "." {
+ build-project $(dir) ;
+ }
+}
+
diff --git a/src/boost/libs/spirit/example/karma/Jamfile b/src/boost/libs/spirit/example/karma/Jamfile
new file mode 100644
index 00000000..a93cbb7a
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/Jamfile
@@ -0,0 +1,38 @@
+#==============================================================================
+# Copyright (c) 2001-2009 Hartmut Kaiser
+# Copyright (c) 2001-2009 Joel de Guzman
+#
+# Distributed under the 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
+ : requirements
+ <c++-template-depth>300
+ :
+ :
+ ;
+
+exe actions_example : actions.cpp ;
+exe auto_facilities : auto_facilities.cpp ;
+exe basic_facilities : basic_facilities.cpp /boost//date_time ;
+exe karma_calc2_ast_dump : calc2_ast_dump.cpp ;
+exe karma_calc2_ast_rpn : calc2_ast_rpn.cpp ;
+exe karma_calc2_ast_vm : calc2_ast_vm.cpp ;
+exe classify_char : classify_char.cpp ;
+exe karma_complex_number : complex_number.cpp ;
+exe karma_complex_number_easier : complex_number_easier.cpp ;
+exe karma_complex_number_adapt : complex_number_adapt.cpp ;
+exe karma_num_list1 : num_list1.cpp ;
+exe karma_num_list2 : num_list2.cpp ;
+exe karma_num_list3 : num_list3.cpp ;
+exe karma_num_matrix : num_matrix.cpp ;
+exe key_value_sequence : key_value_sequence.cpp ;
+exe mini_xml_karma : mini_xml_karma.cpp ;
+exe printf_style_double_format : printf_style_double_format.cpp ;
+exe quick_start1 : quick_start1.cpp ;
+exe karma_reference : reference.cpp ;
+exe karma_reorder_struct : reorder_struct.cpp ;
+exe karma_escaped_string : escaped_string.cpp ;
+exe simple_columns_directive : simple_columns_directive.cpp ;
+exe quoted_strings : quoted_strings.cpp ;
+
diff --git a/src/boost/libs/spirit/example/karma/actions.cpp b/src/boost/libs/spirit/example/karma/actions.cpp
new file mode 100644
index 00000000..d5b5efe2
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/actions.cpp
@@ -0,0 +1,131 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Hartmut Kaiser
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/bind.hpp>
+
+#include <iostream>
+#include <sstream>
+
+// Presented are various ways to attach semantic actions
+// * Using plain function pointer
+// * Using simple function object
+// * Using boost.bind
+// * Using boost.lambda
+
+using boost::spirit::unused_type;
+
+//[karma_tutorial_semantic_action_functions
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+
+ // A plain function
+ void read_function(int& i)
+ {
+ i = 42;
+ }
+
+ // A member function
+ struct reader
+ {
+ void print(int& i) const
+ {
+ i = 42;
+ }
+ };
+
+ // A function object
+ struct read_action
+ {
+ void operator()(int& i, unused_type, unused_type) const
+ {
+ i = 42;
+ }
+ };
+}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ using boost::spirit::karma::int_;
+ using boost::spirit::karma::generate;
+ using client::read_function;
+ using client::reader;
+ using client::read_action;
+
+ { // example using plain functions
+ using namespace boost::spirit;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions1
+ generate(outiter, '{' << int_[&read_function] << '}');
+ //]
+
+ std::cout << "Simple function: " << generated << std::endl;
+ }
+
+ { // example using simple function object
+ using namespace boost::spirit;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions2
+ generate(outiter, '{' << int_[read_action()] << '}');
+ //]
+
+ std::cout << "Simple function object: " << generated << std::endl;
+ }
+
+ { // example using plain function with boost.bind
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions3
+ generate(outiter, '{' << int_[boost::bind(&read_function, _1)] << '}');
+ //]
+
+ std::cout << "Simple function with Boost.Bind: " << generated << std::endl;
+ }
+
+ { // example using member function with boost.bind
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions4
+ reader r;
+ generate(outiter, '{' << int_[boost::bind(&reader::print, &r, _1)] << '}');
+ //]
+
+ std::cout << "Member function: " << generated << std::endl;
+ }
+
+ { // example using boost.lambda
+ namespace lambda = boost::lambda;
+ using namespace boost::spirit;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> outiter(generated);
+
+ //[karma_tutorial_attach_actions5
+ std::stringstream strm("42");
+ generate(outiter, '{' << int_[strm >> lambda::_1] << '}');
+ //]
+
+ std::cout << "Boost.Lambda: " << generated << std::endl;
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/auto_facilities.cpp b/src/boost/libs/spirit/example/karma/auto_facilities.cpp
new file mode 100644
index 00000000..b094f40a
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/auto_facilities.cpp
@@ -0,0 +1,244 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The main purpose of this example is to show the uniform and easy way of
+// output formatting for different container types.
+//
+// The 'auto_' primitive used below is very similar to the 'stream' primitive
+// demonstrated in the example 'basic_facilities.cpp' as it allows to generate
+// output from a multitude of data types. The main difference is that it is
+// mapped to the correct Karma generator instead of using any available
+// operator<<() for the contained data type. Additionally this means, that
+// the format descriptions used below will be usable for any contained type as
+// long as this type has a defined mapping to a Karma generator.
+
+// use a larger value for the alignment field width (default is 10)
+#define BOOST_KARMA_DEFAULT_FIELD_LENGTH 25
+
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+#include <algorithm>
+#include <cstdlib>
+
+#include <boost/range.hpp>
+#include <boost/array.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+#include <boost/fusion/include/array.hpp>
+
+#include <boost/spirit/include/karma.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace traits
+{
+ // We add a specialization for the create_generator customization point
+ // defining a custom output format for the value type of the std::map used
+ // below (std::pair<int const, std::string>). Generally, any specialization
+ // for create_generator is expected to return the proto expression to be
+ // used to generate output for the type the customization point has been
+ // specialized for.
+ //
+ // We need to utilize proto::deep_copy as the expression contains a literal
+ // (the ':') which normally gets embedded in the proto expression by
+ // reference only. The deep copy converts the proto tree to hold this by
+ // value. The deep copy operation can be left out for simpler proto
+ // expressions (not containing references to temporaries). Alternatively
+ // you could use the proto::make_expr() facility to build the required
+ // proto expression.
+ template <>
+ struct create_generator<std::pair<int const, std::string> >
+ {
+ typedef proto::result_of::deep_copy<
+ BOOST_TYPEOF(int_ << ':' << string)
+ >::type type;
+
+ static type call()
+ {
+ return proto::deep_copy(int_ << ':' << string);
+ }
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+// 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 sequence without separators
+ os <<
+ karma::format(
+ auto_, // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ *auto_, // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a space separated sequence
+ os <<
+ karma::format_delimited(
+ auto_, // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format_delimited(
+ *auto_, // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format_delimited(
+ '[' << *auto_ << ']', // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list
+ os <<
+ karma::format(
+ auto_ % ", ", // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (auto_ % ", ") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << -(auto_ % ", ") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (+auto_ | "empty") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a comma separated list of items enclosed in '()'
+ os <<
+ karma::format(
+ ('(' << auto_ << ')') % ", ", // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (
+ ('(' << auto_ << ')') % ", "
+ ) << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a HTML list
+ os <<
+ karma::format_delimited(
+ "<ol>" <<
+ *verbatim["<li>" << auto_ << "</li>"]
+ << "</ol>", // format description
+ '\n', // delimiter
+ c // data
+ ) << std::endl;
+
+ // output the container as right aligned column
+ os <<
+ karma::format_delimited(
+ *verbatim[
+ "|" << right_align[auto_] << "|"
+ ], // format description
+ '\n', // delimiter
+ c // data
+ ) << std::endl;
+
+ os << std::endl;
+}
+
+int main()
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // 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));
+
+ ///////////////////////////////////////////////////////////////////////////
+ // vector
+ std::vector<int> v (5);
+ 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);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // strings
+ std::string str("Hello world!");
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::string" << std::endl;
+ output_container(std::cout, str);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // boost::array
+ boost::array<long, 5> arr;
+ std::generate(arr.begin(), arr.end(), std::rand); // randomly fill the array
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "boost::array<long, 5>" << std::endl;
+ output_container(std::cout, arr);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // map of int --> string mappings
+ std::map<int, std::string> mappings;
+ mappings.insert(std::make_pair(0, "zero"));
+ mappings.insert(std::make_pair(1, "one"));
+ mappings.insert(std::make_pair(2, "two"));
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::map<int, std::string>" << std::endl;
+ output_container(std::cout, mappings);
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/basic_facilities.cpp b/src/boost/libs/spirit/example/karma/basic_facilities.cpp
new file mode 100644
index 00000000..63514032
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/basic_facilities.cpp
@@ -0,0 +1,229 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The main purpose of this example is to show 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/config/warning_disable.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <list>
+#include <map>
+#include <algorithm>
+#include <cstdlib>
+
+#include <boost/range.hpp>
+#include <boost/array.hpp>
+#include <boost/date_time/gregorian/gregorian.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// This streaming operator is needed to generate the output from the map below
+// Yes, it's heresy, but this operator has to live in namespace std to be
+// picked up by the compiler.
+namespace std {
+ inline std::ostream&
+ operator<<(std::ostream& os, std::pair<int const, std::string> v)
+ {
+ os << v.first << ": " << v.second;
+ return os;
+ }
+}
+
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_format.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// 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(
+ *stream, // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ // output the container as a space separated sequence
+ os <<
+ karma::format_delimited(
+ *stream, // format description
+ space, // delimiter
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format_delimited(
+ '[' << *stream << ']', // format description
+ space, // delimiter
+ c // data
+ ) << 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;
+
+ os <<
+ karma::format(
+ '[' << -(stream % ", ") << ']', // format description
+ c // data
+ ) << std::endl << std::endl;
+
+ os <<
+ karma::format(
+ '[' << (+stream | "empty") << ']', // 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
+ '\n', // delimiter
+ c // data
+ ) << std::endl;
+
+ // output the container as right aligned column
+ os <<
+ karma::format_delimited(
+ *verbatim[
+ "|" << right_align[stream] << "|"
+ ], // format description
+ '\n', // delimiter
+ c // data
+ ) << std::endl;
+
+ os << std::endl;
+}
+
+int main()
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // 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));
+
+ ///////////////////////////////////////////////////////////////////////////
+ // vector
+ std::vector<int> v (5);
+ 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);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // strings
+ std::string str("Hello world!");
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::string" << std::endl;
+ output_container(std::cout, str);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // boost::array
+ boost::array<long, 5> arr;
+ std::generate(arr.begin(), arr.end(), std::rand); // randomly fill the array
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "boost::array<long, 5>" << std::endl;
+ output_container(std::cout, arr);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // 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);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // map of int --> string mappings
+ std::map<int, std::string> mappings;
+ mappings.insert(std::make_pair(0, "zero"));
+ mappings.insert(std::make_pair(1, "one"));
+ mappings.insert(std::make_pair(2, "two"));
+
+ std::cout << "-------------------------------------------------------------"
+ << std::endl;
+ std::cout << "std::map<int, std::string>" << std::endl;
+ output_container(std::cout, mappings);
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast.hpp b/src/boost/libs/spirit/example/karma/calc2_ast.hpp
new file mode 100644
index 00000000..d1ee92e8
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast.hpp
@@ -0,0 +1,177 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST which gets dumped into
+// a human readable format afterwards.
+//
+// [ JDG April 28, 2008 ]
+// [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#if !defined(SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM)
+#define SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM
+
+#include <boost/variant.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/karma_domain.hpp>
+#include <boost/spirit/include/support_attributes_fwd.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op;
+struct unary_op;
+struct nil {};
+
+struct expression_ast
+{
+ typedef
+ boost::variant<
+ nil // can't happen!
+ , int
+ , boost::recursive_wrapper<binary_op>
+ , boost::recursive_wrapper<unary_op>
+ >
+ type;
+
+ // expose variant types
+ typedef type::types types;
+
+ // expose variant functionality
+ int which() const { return expr.which(); }
+
+ // constructors
+ expression_ast()
+ : expr(nil()) {}
+
+ expression_ast(unary_op const& expr)
+ : expr(expr) {}
+
+ expression_ast(binary_op const& expr)
+ : expr(expr) {}
+
+ expression_ast(unsigned int expr)
+ : expr(expr) {}
+
+ expression_ast(type const& expr)
+ : expr(expr) {}
+
+ expression_ast& operator+=(expression_ast const& rhs);
+ expression_ast& operator-=(expression_ast const& rhs);
+ expression_ast& operator*=(expression_ast const& rhs);
+ expression_ast& operator/=(expression_ast const& rhs);
+
+ type expr;
+};
+
+// expose variant functionality
+namespace boost
+{
+ // this function has to live in namespace boost for ADL to correctly find it
+ template <typename T>
+ inline T get(expression_ast const& expr)
+ {
+ return boost::get<T>(expr.expr);
+ }
+
+ namespace spirit { namespace traits
+ {
+ // the specialization below tells Spirit to handle expression_ast as
+ // if it where a 'real' variant (if used with Spirit.Karma)
+ template <>
+ struct not_is_variant<expression_ast, karma::domain>
+ : mpl::false_ {};
+
+ // the specialization of variant_which allows to generically extract
+ // the current type stored in the given variant like type
+ template <>
+ struct variant_which<expression_ast>
+ {
+ static int call(expression_ast const& v)
+ {
+ return v.which();
+ }
+ };
+ }}
+}
+
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op
+{
+ binary_op() {}
+
+ binary_op(
+ char op
+ , expression_ast const& left
+ , expression_ast const& right)
+ : op(op), left(left), right(right) {}
+
+ char op;
+ expression_ast left;
+ expression_ast right;
+};
+
+struct unary_op
+{
+ unary_op(
+ char op
+ , expression_ast const& right)
+ : op(op), right(right) {}
+
+ char op;
+ expression_ast right;
+};
+
+inline expression_ast& expression_ast::operator+=(expression_ast const& rhs)
+{
+ expr = binary_op('+', expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator-=(expression_ast const& rhs)
+{
+ expr = binary_op('-', expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator*=(expression_ast const& rhs)
+{
+ expr = binary_op('*', expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator/=(expression_ast const& rhs)
+{
+ expr = binary_op('/', expr, rhs);
+ return *this;
+}
+
+// We should be using expression_ast::operator-. There's a bug
+// in phoenix type deduction mechanism that prevents us from
+// doing so. Phoenix will be switching to BOOST_TYPEOF. In the
+// meantime, we will use a phoenix::function below:
+template <char Op>
+struct unary_expr
+{
+ template <typename T>
+ struct result { typedef T type; };
+
+ expression_ast operator()(expression_ast const& expr) const
+ {
+ return unary_op(Op, expr);
+ }
+};
+
+boost::phoenix::function<unary_expr<'+'> > pos;
+boost::phoenix::function<unary_expr<'-'> > neg;
+
+#endif
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast_dump.cpp b/src/boost/libs/spirit/example/karma/calc2_ast_dump.cpp
new file mode 100644
index 00000000..ac15c7ca
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast_dump.cpp
@@ -0,0 +1,170 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST which gets dumped into
+// a human readable format afterwards.
+//
+// [ JDG April 28, 2008 ]
+// [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "calc2_ast.hpp"
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// Our calculator parser grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator
+ : qi::grammar<Iterator, expression_ast(), space_type>
+{
+ calculator() : calculator::base_type(expression)
+ {
+ 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 = neg(_1)])
+ | ('+' >> factor [_val = pos(_1)])
+ ;
+ }
+
+ qi::rule<Iterator, expression_ast(), space_type> expression, term, factor;
+};
+
+// We need to tell fusion about our binary_op and unary_op structs
+// to make them a first-class fusion citizen
+//
+// Note: we register the members exactly in the same sequence as we need them
+// in the grammar
+BOOST_FUSION_ADAPT_STRUCT(
+ binary_op,
+ (expression_ast, left)
+ (char, op)
+ (expression_ast, right)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ unary_op,
+ (char, op)
+ (expression_ast, right)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST grammar for the generator, this just dumps the AST as a expression
+///////////////////////////////////////////////////////////////////////////////
+template <typename OuputIterator>
+struct dump_ast
+ : karma::grammar<OuputIterator, expression_ast(), space_type>
+{
+ dump_ast() : dump_ast::base_type(ast_node)
+ {
+ ast_node %= int_ | binary_node | unary_node;
+ binary_node %= '(' << ast_node << char_ << ast_node << ')';
+ unary_node %= '(' << char_ << ast_node << ')';
+ }
+
+ karma::rule<OuputIterator, expression_ast(), space_type> ast_node;
+ karma::rule<OuputIterator, binary_op(), space_type> binary_node;
+ karma::rule<OuputIterator, unary_op(), space_type> unary_node;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Dump AST's for simple expressions...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ // Our parser grammar definitions
+ typedef std::string::const_iterator iterator_type;
+ typedef calculator<iterator_type> calculator;
+
+ calculator calc;
+
+ // Our generator grammar definitions
+ typedef std::back_insert_iterator<std::string> output_iterator_type;
+ typedef dump_ast<output_iterator_type> dump_ast;
+
+ dump_ast ast_grammar;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ expression_ast ast;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = qi::phrase_parse(iter, end, calc, space, ast);
+
+ if (r && iter == end)
+ {
+ std::string generated;
+ output_iterator_type outit(generated);
+ r = karma::generate_delimited(outit, ast_grammar, space, ast);
+
+ if (r)
+ {
+ std::cout << "Got AST:" << std::endl << generated
+ << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast_rpn.cpp b/src/boost/libs/spirit/example/karma/calc2_ast_rpn.cpp
new file mode 100644
index 00000000..955f2467
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast_rpn.cpp
@@ -0,0 +1,172 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST which gets dumped into
+// a reverse polish notation afterwards.
+//
+// [ JDG April 28, 2008 ]
+// [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "calc2_ast.hpp"
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// Our calculator parser grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator
+ : qi::grammar<Iterator, expression_ast(), space_type>
+{
+ calculator() : calculator::base_type(expression)
+ {
+ 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 = neg(_1)])
+ | ('+' >> factor [_val = pos(_1)])
+ ;
+ }
+
+ qi::rule<Iterator, expression_ast(), space_type> expression, term, factor;
+};
+
+// We need to tell fusion about our binary_op and unary_op structs
+// to make them a first-class fusion citizen
+//
+// Note: we register the members exactly in the same sequence as we need them
+// in the grammar
+BOOST_FUSION_ADAPT_STRUCT(
+ binary_op,
+ (expression_ast, left)
+ (expression_ast, right)
+ (char, op)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ unary_op,
+ (expression_ast, right)
+ (char, op)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST grammar for the generator, this prints the AST in reverse polish
+// notation
+///////////////////////////////////////////////////////////////////////////////
+template <typename OuputIterator>
+struct ast_rpn
+ : karma::grammar<OuputIterator, expression_ast(), space_type>
+{
+ ast_rpn() : ast_rpn::base_type(ast_node)
+ {
+ ast_node %= int_ | binary_node | unary_node;
+ binary_node %= ast_node << ast_node << char_;
+ unary_node %= '(' << ast_node << char_ << ')';
+ }
+
+ karma::rule<OuputIterator, expression_ast(), space_type> ast_node;
+ karma::rule<OuputIterator, binary_op(), space_type> binary_node;
+ karma::rule<OuputIterator, unary_op(), space_type> unary_node;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "RPN generator for simple expressions...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ // Our parser grammar definitions
+ typedef std::string::const_iterator iterator_type;
+ typedef calculator<iterator_type> calculator;
+
+ calculator calc;
+
+ // Our generator grammar definitions
+ typedef std::back_insert_iterator<std::string> output_iterator_type;
+ typedef ast_rpn<output_iterator_type> ast_rpn;
+
+ ast_rpn ast_grammar;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ expression_ast ast; // this will hold the generated AST
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = qi::phrase_parse(iter, end, calc, space, ast);
+
+ if (r && iter == end)
+ {
+ std::string generated;
+ output_iterator_type outit(generated);
+ r = karma::generate_delimited(outit, ast_grammar, space, ast);
+
+ if (r)
+ {
+ std::cout << "RPN for '" << str << "': \n" << generated
+ << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast_vm.cpp b/src/boost/libs/spirit/example/karma/calc2_ast_vm.cpp
new file mode 100644
index 00000000..77fab096
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast_vm.cpp
@@ -0,0 +1,248 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST from which we generate
+// a simple byte code representation being interpreted by a similar virtual
+// machine.
+//
+// [ JDG April 28, 2008 ]
+// [ HK May 05, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+#include <boost/config/warning_disable.hpp>
+
+#include <iostream>
+#include <vector>
+#include <string>
+
+#include "calc2_ast_vm.hpp"
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// Our calculator parser grammar
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct calculator
+ : qi::grammar<Iterator, expression_ast(), space_type>
+{
+ calculator() : calculator::base_type(expression)
+ {
+ 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 = neg(_1)])
+ | ('+' >> factor [_val = pos(_1)])
+ ;
+ }
+
+ qi::rule<Iterator, expression_ast(), space_type> expression, term, factor;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// The Virtual Machine
+///////////////////////////////////////////////////////////////////////////////
+class vmachine
+{
+public:
+ union element {
+ int code;
+ char bytes[sizeof(int)];
+ };
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ int top() const { return stack_ptr[-1]; };
+ void execute(std::vector<element> const& code);
+
+private:
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+};
+
+void vmachine::execute(std::vector<element> const& code)
+{
+ std::vector<element>::const_iterator pc = code.begin();
+ stack_ptr = stack.begin();
+
+ while ((*pc).code && pc != code.end())
+ {
+ switch ((*pc++).code)
+ {
+ 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++).code;
+ break;
+ }
+ }
+}
+
+// We need to tell fusion about our binary_op and unary_op structs
+// to make them a first-class fusion citizen
+//
+// Note: we register the members exactly in the same sequence as we need them
+// in the grammar
+BOOST_FUSION_ADAPT_STRUCT(
+ binary_op,
+ (expression_ast, left)
+ (expression_ast, right)
+ (int, op)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ unary_op,
+ (expression_ast, right)
+ (int, op)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST grammar for the generator, this just dumps the AST as a expression
+///////////////////////////////////////////////////////////////////////////////
+template <typename OuputIterator, typename Delimiter>
+struct generate_byte_code
+ : karma::grammar<OuputIterator, expression_ast(), Delimiter>
+{
+ generate_byte_code() : generate_byte_code::base_type(ast_node)
+ {
+ ast_node %= int_node | binary_node | unary_node;
+ int_node %= dword(op_int) << dword;
+ binary_node %= ast_node << ast_node << byte_;
+ unary_node %= ast_node << byte_;
+ }
+
+ karma::rule<OuputIterator, expression_ast(), Delimiter> ast_node;
+ karma::rule<OuputIterator, int(), Delimiter> int_node;
+ karma::rule<OuputIterator, binary_op(), Delimiter> binary_node;
+ karma::rule<OuputIterator, unary_op(), Delimiter> unary_node;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// helper function helping to deduce the delimiter type
+template <typename Delimiter>
+bool generate_vm_code(expression_ast const& ast,
+ std::vector<vmachine::element>& code, Delimiter const& d)
+{
+ // Our generator grammar definitions
+ typedef char* output_iterator_type;
+ typedef generate_byte_code<output_iterator_type, Delimiter> generate_byte_code;
+
+ char* outbuffer = (*code.begin()).bytes;
+ generate_byte_code gen_vm;
+ return karma::generate_delimited(outbuffer, gen_vm, d, ast);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Compile simple expressions to bytecode...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ // Our parser grammar definitions
+ typedef std::string::const_iterator iterator_type;
+ typedef calculator<iterator_type> calculator;
+
+ calculator calc;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ expression_ast ast;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = qi::phrase_parse(iter, end, calc, space, ast);
+
+ if (r && iter == end)
+ {
+ // we assume a vm code size of 4096 is sufficient
+ std::vector<vmachine::element> code (4096);
+ r = generate_vm_code(ast, code, pad(4));
+
+ if (r)
+ {
+ vmachine vm;
+ vm.execute(code);
+ std::cout << "\nresult = " << vm.top() << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/calc2_ast_vm.hpp b/src/boost/libs/spirit/example/karma/calc2_ast_vm.hpp
new file mode 100644
index 00000000..b3a51149
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/calc2_ast_vm.hpp
@@ -0,0 +1,190 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST which gets dumped into
+// a human readable format afterwards.
+//
+// [ JDG April 28, 2008 ]
+// [ HK April 28, 2008 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#if !defined(SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM)
+#define SPIRIT_EXAMPLE_CALC2_AST_APR_30_2008_1011AM
+
+#include <boost/variant.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/karma_domain.hpp>
+#include <boost/spirit/include/support_attributes_fwd.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op;
+struct unary_op;
+struct nil {};
+
+struct expression_ast
+{
+ typedef
+ boost::variant<
+ nil // can't happen!
+ , int
+ , boost::recursive_wrapper<binary_op>
+ , boost::recursive_wrapper<unary_op>
+ >
+ type;
+
+ // expose variant types
+ typedef type::types types;
+
+ // expose variant functionality
+ int which() const { return expr.which(); }
+
+ // constructors
+ expression_ast()
+ : expr(nil()) {}
+
+ expression_ast(unary_op const& expr)
+ : expr(expr) {}
+
+ expression_ast(binary_op const& expr)
+ : expr(expr) {}
+
+ expression_ast(unsigned int expr)
+ : expr(expr) {}
+
+ expression_ast(type const& expr)
+ : expr(expr) {}
+
+ expression_ast& operator+=(expression_ast const& rhs);
+ expression_ast& operator-=(expression_ast const& rhs);
+ expression_ast& operator*=(expression_ast const& rhs);
+ expression_ast& operator/=(expression_ast const& rhs);
+
+ type expr;
+};
+
+// expose variant functionality
+namespace boost
+{
+ // this function has to live in namespace boost for ADL to correctly find it
+ template <typename T>
+ inline T get(expression_ast const& expr)
+ {
+ return boost::get<T>(expr.expr);
+ }
+
+ // the specialization below tells Spirit to handle expression_ast as if it
+ // where a 'real' variant
+ namespace spirit { namespace traits
+ {
+ // the specialization below tells Spirit to handle expression_ast as
+ // if it where a 'real' variant (if used with Spirit.Karma)
+ template <>
+ struct not_is_variant<expression_ast, karma::domain>
+ : mpl::false_ {};
+
+ // the specialization of variant_which allows to generically extract
+ // the current type stored in the given variant like type
+ template <>
+ struct variant_which<expression_ast>
+ {
+ static int call(expression_ast const& v)
+ {
+ return v.which();
+ }
+ };
+ }}
+}
+
+enum byte_code
+{
+ op_neg = 1, // negate the top stack entry
+ op_pos, // essentially a no-op (unary plus)
+ 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
+};
+
+///////////////////////////////////////////////////////////////////////////////
+struct binary_op
+{
+ binary_op() {}
+
+ binary_op(
+ int op
+ , expression_ast const& left
+ , expression_ast const& right)
+ : op(op), left(left), right(right) {}
+
+ int op;
+ expression_ast left;
+ expression_ast right;
+};
+
+struct unary_op
+{
+ unary_op(
+ int op
+ , expression_ast const& right)
+ : op(op), right(right) {}
+
+ int op;
+ expression_ast right;
+};
+
+inline expression_ast& expression_ast::operator+=(expression_ast const& rhs)
+{
+ expr = binary_op(op_add, expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator-=(expression_ast const& rhs)
+{
+ expr = binary_op(op_sub, expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator*=(expression_ast const& rhs)
+{
+ expr = binary_op(op_mul, expr, rhs);
+ return *this;
+}
+
+inline expression_ast& expression_ast::operator/=(expression_ast const& rhs)
+{
+ expr = binary_op(op_div, expr, rhs);
+ return *this;
+}
+
+// We should be using expression_ast::operator-. There's a bug
+// in phoenix type deduction mechanism that prevents us from
+// doing so. Phoenix will be switching to BOOST_TYPEOF. In the
+// meantime, we will use a phoenix::function below:
+template <char Op>
+struct unary_expr
+{
+ template <typename T>
+ struct result { typedef T type; };
+
+ expression_ast operator()(expression_ast const& expr) const
+ {
+ return unary_op(Op, expr);
+ }
+};
+
+boost::phoenix::function<unary_expr<op_pos> > pos;
+boost::phoenix::function<unary_expr<op_neg> > neg;
+
+#endif
diff --git a/src/boost/libs/spirit/example/karma/classify_char.cpp b/src/boost/libs/spirit/example/karma/classify_char.cpp
new file mode 100644
index 00000000..df113f33
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/classify_char.cpp
@@ -0,0 +1,103 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A character classification example
+//
+// [ HK August 12, 2009 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#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/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our character classification generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_complex_number
+ template <typename OutputIterator>
+ bool classify_character(OutputIterator sink, char c)
+ {
+ using boost::spirit::ascii::char_;
+ using boost::spirit::ascii::digit;
+ using boost::spirit::ascii::xdigit;
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::ascii::punct;
+ using boost::spirit::ascii::space;
+ using boost::spirit::ascii::cntrl;
+ using boost::spirit::karma::omit;
+ using boost::spirit::karma::generate;
+
+ if (!boost::spirit::char_encoding::ascii::isascii_(c))
+ return false;
+
+ return generate(sink,
+ // Begin grammar
+ (
+ "The character '" << char_ << "' is "
+ << ( &digit << "a digit"
+ | &xdigit << "a xdigit"
+ | &alpha << "a alpha"
+ | &punct << "a punct"
+ | &space << "a space"
+ | &cntrl << "a cntrl"
+ | "of unknown type"
+ )
+ ),
+ // End grammar
+ c, c
+ );
+ }
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA character classification micro generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a character to classify\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::classify_character(sink, str[0]))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << generated << "\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/complex_number.cpp b/src/boost/libs/spirit/example/karma/complex_number.cpp
new file mode 100644
index 00000000..d832553b
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/complex_number.cpp
@@ -0,0 +1,132 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+// Copyright (c) 2001-2010 Joel de Guzman
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A complex number micro generator.
+//
+// [ HK July 7, 2009 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#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/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number parser/compiler (that's just a copy of the complex
+ // number example from Qi (see examples/qi/complex_number.cpp)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+ using boost::phoenix::ref;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ bool r = phrase_parse(first, last,
+ (
+ '(' >> double_[ref(rN) = _1]
+ >> -(',' >> double_[ref(iN) = _1]) >> ')'
+ | double_[ref(rN) = _1]
+ ),
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_complex_number
+ template <typename OutputIterator>
+ bool generate_complex(OutputIterator sink, std::complex<double> const& c)
+ {
+ using boost::spirit::karma::eps;
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::_1;
+ using boost::spirit::karma::generate;
+
+ return generate(sink,
+ // Begin grammar
+ (
+ eps(c.imag() != 0) <<
+ '(' << double_[_1 = c.real()] << ", " << double_[_1 = c.imag()] << ')'
+ | double_[_1 = c.real()]
+ )
+ // End grammar
+ );
+ }
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_complex(sink, c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/complex_number_adapt.cpp b/src/boost/libs/spirit/example/karma/complex_number_adapt.cpp
new file mode 100644
index 00000000..25135e08
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/complex_number_adapt.cpp
@@ -0,0 +1,153 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+// Copyright (c) 2001-2010 Joel de Guzman
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A complex number micro generator - take 3.
+//
+// Look'ma, still no semantic actions! And no explicit access to member
+// functions any more.
+//
+// [ HK April 6, 2010 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#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/fusion/include/std_pair.hpp>
+#include <boost/fusion/include/adapt_adt.hpp>
+#include <boost/spirit/include/support_adapt_adt_attributes.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+///////////////////////////////////////////////////////////////////////////////
+// The following macro adapts the type std::complex<double> as a fusion
+// sequence.
+//[tutorial_karma_complex_number_adapt_class
+// We can leave off the setters as Karma does not need them.
+BOOST_FUSION_ADAPT_ADT(
+ std::complex<double>,
+ (bool, bool, obj.imag() != 0, /**/)
+ (double, double, obj.real(), /**/)
+ (double, double, obj.imag(), /**/)
+)
+//]
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number parser/compiler (that's just a copy of the complex
+ // number example from Qi (see examples/qi/complex_number.cpp)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+ using boost::phoenix::ref;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ bool r = phrase_parse(first, last,
+ (
+ '(' >> double_[ref(rN) = _1]
+ >> -(',' >> double_[ref(iN) = _1]) >> ')'
+ | double_[ref(rN) = _1]
+ ),
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_complex_number_adapt
+ template <typename OutputIterator>
+ bool generate_complex(OutputIterator sink, std::complex<double> const& c)
+ {
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::bool_;
+ using boost::spirit::karma::true_;
+ using boost::spirit::karma::omit;
+ using boost::spirit::karma::generate;
+
+ return generate(sink,
+
+ // Begin grammar
+ (
+ &true_ << '(' << double_ << ", " << double_ << ')'
+ | omit[bool_] << double_
+ ),
+ // End grammar
+
+ c // Data to output
+ );
+ }
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_complex(sink, c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/complex_number_easier.cpp b/src/boost/libs/spirit/example/karma/complex_number_easier.cpp
new file mode 100644
index 00000000..0fe05149
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/complex_number_easier.cpp
@@ -0,0 +1,133 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+// Copyright (c) 2001-2010 Joel de Guzman
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// A complex number micro generator - take 2. Look'ma no semantic actions!
+//
+// [ HK July 26, 2009 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#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/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number parser/compiler (that's just a copy of the complex
+ // number example from Qi (see examples/qi/complex_number.cpp)
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+ using boost::phoenix::ref;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ bool r = phrase_parse(first, last,
+ (
+ '(' >> double_[ref(rN) = _1]
+ >> -(',' >> double_[ref(iN) = _1]) >> ')'
+ | double_[ref(rN) = _1]
+ ),
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our complex number generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_complex_number_easier
+ template <typename OutputIterator>
+ bool generate_complex(OutputIterator sink, std::complex<double> const& c)
+ {
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::omit;
+ using boost::spirit::karma::generate;
+
+ return generate(sink,
+
+ // Begin grammar
+ (
+ !double_(0.0) << '(' << double_ << ", " << double_ << ')'
+ | omit[double_] << double_
+ ),
+ // End grammar
+
+ c.imag(), c.real(), c.imag() // Data to output
+ );
+ }
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_complex(sink, c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/customize_counter.cpp b/src/boost/libs/spirit/example/karma/customize_counter.cpp
new file mode 100644
index 00000000..62506928
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/customize_counter.cpp
@@ -0,0 +1,127 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+
+//[customize_karma_counter_includes
+#include <boost/spirit/include/karma.hpp>
+#include <iostream>
+#include <vector>
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[customize_karma_counter_data
+namespace client
+{
+ struct counter
+ {
+ // expose the current value of the counter as our iterator
+ typedef int iterator;
+
+ // expose 'int' as the type of each generated element
+ typedef int type;
+
+ counter(int max_count)
+ : counter_(0), max_count_(max_count)
+ {}
+
+ int counter_;
+ int max_count_;
+ };
+}
+//]
+
+//[customize_karma_counter_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+//
+// Note that all templates below are specialized using the 'const' type.
+// This is necessary as all attributes in Karma are 'const'.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'is_container<>' will tell the
+ // library to treat the type 'client::counter' as a container providing
+ // the items to generate output from.
+ template <>
+ struct is_container<client::counter const>
+ : mpl::true_
+ {};
+
+ // The specialization of the template 'container_iterator<>' will be
+ // invoked by the library to evaluate the iterator type to be used
+ // for iterating the data elements in the container.
+ template <>
+ struct container_iterator<client::counter const>
+ {
+ typedef client::counter::iterator type;
+ };
+
+ // The specialization of the templates 'begin_container<>' and
+ // 'end_container<>' below will be used by the library to get the iterators
+ // pointing to the begin and the end of the data to generate output from.
+ // These specializations respectively return the initial and maximum
+ // counter values.
+ //
+ // The passed argument refers to the attribute instance passed to the list
+ // generator.
+ template <>
+ struct begin_container<client::counter const>
+ {
+ static client::counter::iterator
+ call(client::counter const& c)
+ {
+ return c.counter_;
+ }
+ };
+
+ template <>
+ struct end_container<client::counter const>
+ {
+ static client::counter::iterator
+ call(client::counter const& c)
+ {
+ return c.max_count_;
+ }
+ };
+}}}
+//]
+
+//[customize_karma_counter_iterator_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'deref_iterator<>' will be used to
+ // dereference the iterator associated with our counter data structure.
+ // Since we expose the current value as the iterator we just return the
+ // current iterator as the return value.
+ template <>
+ struct deref_iterator<client::counter::iterator>
+ {
+ typedef client::counter::type type;
+
+ static type call(client::counter::iterator const& it)
+ {
+ return it;
+ }
+ };
+}}}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+namespace karma = boost::spirit::karma;
+
+int main()
+{
+ //[customize_karma_counter
+ // use the instance of a 'client::counter' instead of a STL vector
+ client::counter count(4);
+ std::cout << karma::format(karma::int_ % ", ", count) << std::endl; // prints: '0, 1, 2, 3'
+ //]
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/customize_embedded_container.cpp b/src/boost/libs/spirit/example/karma/customize_embedded_container.cpp
new file mode 100644
index 00000000..c0c071b4
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/customize_embedded_container.cpp
@@ -0,0 +1,108 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+
+//[customize_karma_embedded_container_includes
+#include <boost/spirit/include/karma.hpp>
+#include <iostream>
+#include <vector>
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[customize_karma_embedded_container_data
+namespace client
+{
+ struct embedded_container
+ {
+ // expose the iterator of the embedded vector as our iterator
+ typedef std::vector<int>::const_iterator iterator;
+
+ // expose the type of the held data elements as our type
+ typedef std::vector<int>::value_type type;
+
+ // this is the vector holding the actual elements we need to generate
+ // output from
+ std::vector<int> data;
+ };
+}
+//]
+
+//[customize_karma_embedded_container_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+//
+// Note that all templates below are specialized using the 'const' type.
+// This is necessary as all attributes in Karma are 'const'.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'is_container<>' will tell the
+ // library to treat the type 'client::embedded_container' as a
+ // container holding the items to generate output from.
+ template <>
+ struct is_container<client::embedded_container const>
+ : mpl::true_
+ {};
+
+ // The specialization of the template 'container_iterator<>' will be
+ // invoked by the library to evaluate the iterator type to be used
+ // for iterating the data elements in the container. We simply return
+ // the type of the iterator exposed by the embedded 'std::vector<int>'.
+ template <>
+ struct container_iterator<client::embedded_container const>
+ {
+ typedef client::embedded_container::iterator type;
+ };
+
+ // The specialization of the templates 'begin_container<>' and
+ // 'end_container<>' below will be used by the library to get the iterators
+ // pointing to the begin and the end of the data to generate output from.
+ // These specializations simply return the 'begin' and 'end' iterators as
+ // exposed by the embedded 'std::vector<int>'.
+ //
+ // The passed argument refers to the attribute instance passed to the list
+ // generator.
+ template <>
+ struct begin_container<client::embedded_container const>
+ {
+ static client::embedded_container::iterator
+ call(client::embedded_container const& d)
+ {
+ return d.data.begin();
+ }
+ };
+
+ template <>
+ struct end_container<client::embedded_container const>
+ {
+ static client::embedded_container::iterator
+ call(client::embedded_container const& d)
+ {
+ return d.data.end();
+ }
+ };
+}}}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+namespace karma = boost::spirit::karma;
+
+int main()
+{
+ //[customize_karma_embedded_container
+ client::embedded_container d1; // create some test data
+ d1.data.push_back(1);
+ d1.data.push_back(2);
+ d1.data.push_back(3);
+
+ // use the instance of an 'client::embedded_container' instead of a
+ // STL vector
+ std::cout << karma::format(karma::int_ % ", ", d1) << std::endl; // prints: '1, 2, 3'
+ //]
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/customize_use_as_container.cpp b/src/boost/libs/spirit/example/karma/customize_use_as_container.cpp
new file mode 100644
index 00000000..c0116c8a
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/customize_use_as_container.cpp
@@ -0,0 +1,164 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+
+//[customize_karma_use_as_container_includes
+#include <boost/spirit/include/karma.hpp>
+#include <iostream>
+#include <string>
+#include <vector>
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[customize_karma_use_as_container_data
+namespace client
+{
+ struct use_as_container
+ {
+ // Expose a pair holding a pointer to the use_as_container and to the
+ // current element as our iterator.
+ // We intentionally leave out having it a 'operator==()' to demonstrate
+ // the use of the 'compare_iterators' customization point.
+ struct iterator
+ {
+ iterator(use_as_container const* container, int const* current)
+ : container_(container), current_(current)
+ {}
+
+ use_as_container const* container_;
+ int const* current_;
+ };
+
+ // expose 'int' as the type of each generated element
+ typedef int type;
+
+ use_as_container(int value1, int value2, int value3)
+ : value1_(value1), value2_(value2), value3_(value3)
+ {}
+
+ int value1_;
+ std::string dummy1_; // insert some unrelated data
+ int value2_;
+ std::string dummy2_; // insert some more unrelated data
+ int value3_;
+ };
+}
+//]
+
+//[customize_karma_use_as_container_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+//
+// Note that all templates below are specialized using the 'const' type.
+// This is necessary as all attributes in Karma are 'const'.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'is_container<>' will tell the
+ // library to treat the type 'client::use_as_container' as a
+ // container holding the items to generate output from.
+ template <>
+ struct is_container<client::use_as_container const>
+ : mpl::true_
+ {};
+
+ // The specialization of the template 'container_iterator<>' will be
+ // invoked by the library to evaluate the iterator type to be used
+ // for iterating the data elements in the container. We simply return
+ // the type of the iterator exposed by the embedded 'std::vector<int>'.
+ template <>
+ struct container_iterator<client::use_as_container const>
+ {
+ typedef client::use_as_container::iterator type;
+ };
+
+ // The specialization of the templates 'begin_container<>' and
+ // 'end_container<>' below will be used by the library to get the iterators
+ // pointing to the begin and the end of the data to generate output from.
+ //
+ // The passed argument refers to the attribute instance passed to the list
+ // generator.
+ template <>
+ struct begin_container<client::use_as_container const>
+ {
+ static client::use_as_container::iterator
+ call(client::use_as_container const& c)
+ {
+ return client::use_as_container::iterator(&c, &c.value1_);
+ }
+ };
+
+ template <>
+ struct end_container<client::use_as_container const>
+ {
+ static client::use_as_container::iterator
+ call(client::use_as_container const& c)
+ {
+ return client::use_as_container::iterator(&c, (int const*)0);
+ }
+ };
+}}}
+//]
+
+//[customize_karma_use_as_container_iterator_traits
+// All specializations of attribute customization points have to be placed into
+// the namespace boost::spirit::traits.
+namespace boost { namespace spirit { namespace traits
+{
+ // The specialization of the template 'deref_iterator<>' will be used to
+ // dereference the iterator associated with our counter data structure.
+ template <>
+ struct deref_iterator<client::use_as_container::iterator>
+ {
+ typedef client::use_as_container::type type;
+
+ static type call(client::use_as_container::iterator const& it)
+ {
+ return *it.current_;
+ }
+ };
+
+ template <>
+ struct next_iterator<client::use_as_container::iterator>
+ {
+ static void call(client::use_as_container::iterator& it)
+ {
+ if (it.current_ == &it.container_->value1_)
+ it.current_ = &it.container_->value2_;
+ else if (it.current_ == &it.container_->value2_)
+ it.current_ = &it.container_->value3_;
+ else
+ it.current_ = 0;
+ }
+ };
+
+ template <>
+ struct compare_iterators<client::use_as_container::iterator>
+ {
+ static bool call(client::use_as_container::iterator const& it1
+ , client::use_as_container::iterator const& it2)
+ {
+ return it1.current_ == it2.current_ &&
+ it1.container_ == it2.container_;
+ }
+ };
+}}}
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+namespace karma = boost::spirit::karma;
+
+int main()
+{
+ //[customize_karma_use_as_container
+ client::use_as_container d2 (1, 2, 3);
+ // use the instance of a 'client::use_as_container' instead of a STL vector
+ std::cout << karma::format(karma::int_ % ", ", d2) << std::endl; // prints: '1, 2, 3'
+ //]
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/escaped_string.cpp b/src/boost/libs/spirit/example/karma/escaped_string.cpp
new file mode 100644
index 00000000..f3c2fe6f
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/escaped_string.cpp
@@ -0,0 +1,66 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how any character sequence can be
+// printed while being properly quoted.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+
+ template <typename OutputIterator>
+ struct escaped_string
+ : karma::grammar<OutputIterator, std::string(char const*)>
+ {
+ escaped_string()
+ : escaped_string::base_type(esc_str)
+ {
+ esc_char.add('\a', "\\a")('\b', "\\b")('\f', "\\f")('\n', "\\n")
+ ('\r', "\\r")('\t', "\\t")('\v', "\\v")('\\', "\\\\")
+ ('\'', "\\\'")('\"', "\\\"")
+ ;
+
+ esc_str = karma::lit(karma::_r1)
+ << *(esc_char | karma::print | "\\x" << karma::hex)
+ << karma::lit(karma::_r1)
+ ;
+ }
+
+ karma::rule<OutputIterator, std::string(char const*)> esc_str;
+ karma::symbols<char, char const*> esc_char;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace karma = boost::spirit::karma;
+
+ typedef std::back_insert_iterator<std::string> sink_type;
+
+ std::string generated;
+ sink_type sink(generated);
+
+ std::string str("string to escape: \n\r\t\"'\x19");
+ char const* quote = "'''";
+
+ client::escaped_string<sink_type> g;
+ if (!karma::generate(sink, g(quote), str))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/generate_code.cpp b/src/boost/libs/spirit/example/karma/generate_code.cpp
new file mode 100644
index 00000000..3a409a77
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/generate_code.cpp
@@ -0,0 +1,80 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// Several small snippets generating different C++ code constructs
+//
+// [ HK October 08, 2009 ] Spirit V2.2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+ namespace phoenix = boost::phoenix;
+
+ // create for instance: int name[5] = { 1, 2, 3, 4, 5 };
+ template <typename Iterator>
+ struct int_array : karma::grammar<Iterator, std::vector<int>()>
+ {
+ int_array(char const* name) : int_array::base_type(start)
+ {
+ using karma::int_;
+ using karma::uint_;
+ using karma::eol;
+ using karma::lit;
+ using karma::_val;
+ using karma::_r1;
+
+ start = array_def(phoenix::size(_val)) << " = " << initializer
+ << ';' << eol;
+ array_def = "int " << lit(name) << "[" << uint_(_r1) << "]";
+ initializer = "{ " << -(int_ % ", ") << " }";
+ }
+
+ karma::rule<Iterator, void(unsigned)> array_def;
+ karma::rule<Iterator, std::vector<int>()> initializer;
+ karma::rule<Iterator, std::vector<int>()> start;
+ };
+
+ typedef std::back_insert_iterator<std::string> iterator_type;
+ bool generate_array(char const* name, std::vector<int> const& v)
+ {
+ std::string generated;
+ iterator_type sink(generated);
+ int_array<iterator_type> g(name);
+ if (karma::generate(sink, g, v))
+ {
+ std::cout << generated;
+ return true;
+ }
+ return false;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ // generate an array of integers with initializers
+ std::vector<int> v;
+ v.push_back(1);
+ v.push_back(2);
+ v.push_back(3);
+ v.push_back(4);
+ client::generate_array("array1", v);
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/key_value_sequence.cpp b/src/boost/libs/spirit/example/karma/key_value_sequence.cpp
new file mode 100644
index 00000000..db2de2cc
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/key_value_sequence.cpp
@@ -0,0 +1,74 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The main purpose of this example is to show how we can generate output from
+// a container holding key/value pairs.
+//
+// For more information see here: http://spirit.sourceforge.net/home/?p=400
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/karma_stream.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <map>
+#include <algorithm>
+#include <cstdlib>
+
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+
+ typedef std::pair<std::string, boost::optional<std::string> > pair_type;
+
+ template <typename OutputIterator>
+ struct keys_and_values
+ : karma::grammar<OutputIterator, std::vector<pair_type>()>
+ {
+ keys_and_values()
+ : keys_and_values::base_type(query)
+ {
+ query = pair << *('&' << pair);
+ pair = karma::string << -('=' << karma::string);
+ }
+
+ karma::rule<OutputIterator, std::vector<pair_type>()> query;
+ karma::rule<OutputIterator, pair_type()> pair;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace karma = boost::spirit::karma;
+
+ typedef std::vector<client::pair_type>::value_type value_type;
+ typedef std::back_insert_iterator<std::string> sink_type;
+
+ std::vector<client::pair_type> v;
+ v.push_back(value_type("key1", boost::optional<std::string>("value1")));
+ v.push_back(value_type("key2", boost::optional<std::string>()));
+ v.push_back(value_type("key3", boost::optional<std::string>("")));
+
+ std::string generated;
+ sink_type sink(generated);
+ client::keys_and_values<sink_type> g;
+ if (!karma::generate(sink, g, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/mini_xml_karma.cpp b/src/boost/libs/spirit/example/karma/mini_xml_karma.cpp
new file mode 100644
index 00000000..596fd78c
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/mini_xml_karma.cpp
@@ -0,0 +1,222 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+ Copyright (c) 2001-2010 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// 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/config/warning_disable.hpp>
+
+#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_function.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/variant/recursive_variant.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+using namespace boost::spirit;
+using namespace boost::spirit::ascii;
+
+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<Iterator, mini_xml(), space_type>
+{
+ mini_xml_parser() : mini_xml_parser::base_type(xml)
+ {
+ text = lexeme[+(char_ - '<') [_val += _1]];
+ node = (xml | text) [_val = _1];
+
+ start_tag =
+ '<'
+ >> !lit('/')
+ >> lexeme[+(char_ - '>') [_val += _1]]
+ >> '>'
+ ;
+
+ end_tag =
+ "</"
+ >> lit(_r1)
+ >> '>'
+ ;
+
+ xml =
+ start_tag [at_c<0>(_val) = _1]
+ >> *node [push_back(at_c<1>(_val), _1)]
+ >> end_tag(at_c<0>(_val))
+ ;
+ }
+
+ qi::rule<Iterator, mini_xml(), 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;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// A couple of phoenix functions helping to access the elements of the
+// generated AST
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+struct get_element
+{
+ template <typename T1>
+ struct result { typedef T const& type; };
+
+ T const& operator()(mini_xml_node const& node) const
+ {
+ return boost::get<T>(node);
+ }
+};
+
+phoenix::function<get_element<std::string> > _string;
+phoenix::function<get_element<mini_xml> > _xml;
+
+///////////////////////////////////////////////////////////////////////////////
+// The output grammar defining the format of the generated data
+///////////////////////////////////////////////////////////////////////////////
+template <typename OutputIterator>
+struct mini_xml_generator
+ : karma::grammar<OutputIterator, mini_xml()>
+{
+ mini_xml_generator() : mini_xml_generator::base_type(xml)
+ {
+ node %= string | xml;
+ xml =
+ '<' << string[_1 = at_c<0>(_val)] << '>'
+ << (*node)[_1 = at_c<1>(_val)]
+ << "</" << string[_1 = at_c<0>(_val)] << '>'
+ ;
+ }
+
+ karma::rule<OutputIterator, mini_xml()> xml;
+ karma::rule<OutputIterator, mini_xml_node()> node;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// 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 xmlin; // Our grammar definition
+ mini_xml ast; // our tree
+
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = qi::phrase_parse(iter, end, xmlin, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+
+ typedef std::back_insert_iterator<std::string> outiter_type;
+ typedef mini_xml_generator<outiter_type> mini_xml_generator;
+
+ mini_xml_generator xmlout; // Our grammar definition
+
+ std::string generated;
+ outiter_type outit(generated);
+ bool r = karma::generate(outit, xmlout, ast);
+
+ if (r)
+ std::cout << generated << std::endl;
+ return 0;
+ }
+ else
+ {
+ std::string::const_iterator begin = storage.begin();
+ std::size_t dist = std::distance(begin, iter);
+ std::string::const_iterator some =
+ iter + (std::min)(storage.size()-dist, std::size_t(30));
+ std::string context(iter, some);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << context << "...\"\n";
+ std::cout << "-------------------------\n";
+ return 1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/num_list1.cpp b/src/boost/libs/spirit/example/karma/num_list1.cpp
new file mode 100644
index 00000000..7b079b04
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/num_list1.cpp
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Hartmut Kaiser
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demonstrates a generator for a comma separated list of numbers.
+// No actions. It is based on the example qi/num_lists.cpp for reading in
+// some numbers to generate.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+#include <iostream>
+#include <string>
+#include <list>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace karma = boost::spirit::karma;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser, please see the example qi/numlist1.cpp for
+ // more information
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::list<double>& v)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using ascii::space;
+
+ bool r = phrase_parse(first, last, double_ >> *(',' >> double_), space, v);
+ if (first != last)
+ return false;
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_numlist1
+ template <typename OutputIterator>
+ bool generate_numbers(OutputIterator& sink, std::list<double> const& v)
+ {
+ using karma::double_;
+ using karma::generate_delimited;
+ using ascii::space;
+
+ bool r = generate_delimited(
+ sink, // destination: output iterator
+ double_ << *(',' << double_), // the generator
+ space, // the delimiter-generator
+ v // the data to output
+ );
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::list<double> v; // here we put the data to generate
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ // ok, we got some numbers, now print them back out
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_numbers(sink, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/num_list2.cpp b/src/boost/libs/spirit/example/karma/num_list2.cpp
new file mode 100644
index 00000000..ce16fafe
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/num_list2.cpp
@@ -0,0 +1,117 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Hartmut Kaiser
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demonstrates a generator for a comma separated list of numbers.
+// No actions. It is based on the example qi/num_lists.cpp for reading in
+// some numbers to generate.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser, please see the example qi/numlist1.cpp for
+ // more information
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+
+ bool r = phrase_parse(first, last, double_ % ',', space, v);
+ if (first != last)
+ return false;
+ return r;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_numlist2
+ template <typename OutputIterator, typename Container>
+ bool generate_numbers(OutputIterator& sink, Container const& v)
+ {
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::generate_delimited;
+ using boost::spirit::ascii::space;
+
+ bool r = generate_delimited(
+ sink, // destination: output iterator
+ double_ % ',', // the generator
+ space, // the delimiter-generator
+ v // the data to output
+ );
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v; // here we put the data to generate
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ // ok, we got some numbers, now print them back out
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_numbers(sink, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/num_list3.cpp b/src/boost/libs/spirit/example/karma/num_list3.cpp
new file mode 100644
index 00000000..253de1b4
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/num_list3.cpp
@@ -0,0 +1,150 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Hartmut Kaiser
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demonstrates a generator for a comma separated list of numbers.
+// No actions. It is based on the example qi/num_lists.cpp for reading in
+// some numbers to generate.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser, please see the example qi/numlist1.cpp for
+ // more information
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+
+ bool r = phrase_parse(first, last, double_ % ',', space, v);
+ if (first != last)
+ return false;
+ return r;
+ }
+
+ //[tutorial_karma_numlist3_complex
+ // a simple complex number representation z = a + bi
+ struct complex
+ {
+ complex (double a, double b = 0.0) : a(a), b(b) {}
+
+ double a;
+ double b;
+ };
+
+ // the streaming operator for the type complex
+ std::ostream&
+ operator<< (std::ostream& os, complex const& z)
+ {
+ os << "{" << z.a << "," << z.b << "}";
+ return os;
+ }
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_numlist3
+ template <typename OutputIterator, typename Container>
+ bool generate_numbers(OutputIterator& sink, Container const& v)
+ {
+ using boost::spirit::karma::stream;
+ using boost::spirit::karma::generate;
+ using boost::spirit::karma::eol;
+
+ bool r = generate(
+ sink, // destination: output iterator
+ stream % eol, // the generator
+ v // the data to output
+ );
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\tA comma separated list generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v; // here we put the data gotten from input
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ // ok, we got some numbers, fill a vector of client::complex
+ // instances and print them back out
+ std::vector<client::complex> vc;
+ std::vector<double>::const_iterator end = v.end();
+ for (std::vector<double>::const_iterator it = v.begin();
+ it != end; ++it)
+ {
+ double real(*it);
+ if (++it != end)
+ vc.push_back(client::complex(real, *it));
+ else {
+ vc.push_back(client::complex(real));
+ break;
+ }
+ }
+
+ std::cout << "-------------------------\n";
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_numbers(sink, vc))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated:\n" << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/num_matrix.cpp b/src/boost/libs/spirit/example/karma/num_matrix.cpp
new file mode 100644
index 00000000..0622e096
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/num_matrix.cpp
@@ -0,0 +1,114 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Hartmut Kaiser
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demonstrates a generator formatting and printing a matrix
+// of integers taken from a simple vector of vectors. The size and the
+// contents of the printed matrix is generated randomly.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <ctime>
+
+namespace karma = boost::spirit::karma;
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our matrix generator
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_karma_nummatrix_grammar
+ template <typename OutputIterator>
+ struct matrix_grammar
+ : karma::grammar<OutputIterator, std::vector<std::vector<int> >()>
+ {
+ matrix_grammar()
+ : matrix_grammar::base_type(matrix)
+ {
+ using karma::int_;
+ using karma::right_align;
+ using karma::eol;
+
+ element = right_align(10)[int_];
+ row = '|' << *element << '|';
+ matrix = row % eol;
+ }
+
+ karma::rule<OutputIterator, std::vector<std::vector<int> >()> matrix;
+ karma::rule<OutputIterator, std::vector<int>()> row;
+ karma::rule<OutputIterator, int()> element;
+ };
+ //]
+
+ //[tutorial_karma_nummatrix
+ template <typename OutputIterator>
+ bool generate_matrix(OutputIterator& sink
+ , std::vector<std::vector<int> > const& v)
+ {
+ matrix_grammar<OutputIterator> matrix;
+ return karma::generate(
+ sink, // destination: output iterator
+ matrix, // the generator
+ v // the data to output
+ );
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\tPrinting integers in a matrix using Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ // here we put the data to generate
+ std::vector<std::vector<int> > v;
+
+ // now, generate the size and the contents for the matrix
+ std::srand((unsigned int)std::time(NULL));
+ std::size_t rows = std::rand() / (RAND_MAX / 10);
+ std::size_t columns = std::rand() / (RAND_MAX / 10);
+
+ v.resize(rows);
+ for (std::size_t row = 0; row < rows; ++row)
+ {
+ v[row].resize(columns);
+ std::generate(v[row].begin(), v[row].end(), std::rand);
+ }
+
+ // ok, we got the matrix, now print it out
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!client::generate_matrix(sink, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated:\n" << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/karma/printf_style_double_format.cpp b/src/boost/libs/spirit/example/karma/printf_style_double_format.cpp
new file mode 100644
index 00000000..b1c094da
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/printf_style_double_format.cpp
@@ -0,0 +1,282 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The main purpose of this example is to show how a single container type can
+// be formatted using different output grammars.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <cmath>
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+// This policy allows to use printf style formatting specifiers for Karma
+// floating point generators. This policy understands the following format:
+//
+// The format string must conform to the following format, otherwise a
+// std::runtime_error will be thrown:
+//
+// %[flags][fill][width][.precision]type
+//
+// where:
+// flags (only one possible):
+// +: Always denote the sign '+' or '-' of a number
+// -: Left-align the output
+// fill:
+// 0: Uses 0 instead of spaces to left-fill a fixed-length field
+// width:
+// number: Left-pad the output with spaces until it is at least number
+// characters wide. if number has a leading '0', that is
+// interpreted as a 'fill', the padding is done with '0'
+// characters instead of spaces.
+// precision:
+// number: Causes the decimal portion of the output to be expressed
+// in at least number digits
+// type (only one possible):
+// e: force scientific notation, with a lowercase "e"
+// E: force scientific notation, with a uppercase "E"
+// f: floating point format
+// g: use %e or %f, whichever is shorter
+// G: use %E or %f, whichever is shorter
+//
+
+///////////////////////////////////////////////////////////////////////////////
+// define a data structure and a corresponding parser to hold the formatting
+// information extracted from the format specification string
+namespace client
+{
+ struct format_data
+ {
+ char flag;
+ char fill;
+ int width;
+ int precision;
+ char type;
+ };
+}
+
+// We need to tell fusion about our format_data struct
+// to make it a first-class fusion citizen
+BOOST_FUSION_ADAPT_STRUCT(
+ client::format_data,
+ (char, flag)
+ (char, fill)
+ (int, width)
+ (int, precision)
+ (char, type)
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Grammar for format specification string as described above
+ template <typename Iterator>
+ struct format_grammar : qi::grammar<Iterator, format_data()>
+ {
+ format_grammar() : format_grammar::base_type(format)
+ {
+ using qi::uint_;
+ using qi::attr;
+ using ascii::char_;
+ using ascii::no_case;
+
+ format %= '%' >> flags >> fill >> width >> prec >> type;
+
+ // default flags is right aligned
+ flags = char_('+') | char_('-') | attr(' ');
+ fill = char_('0') | attr(' '); // default fill is space
+ width = uint_ | attr(-1);
+ prec = '.' >> uint_ | attr(3); // default is 3 digits
+ type = no_case[char_('e')] | char_('f') | no_case[char_('g')];
+ };
+
+ qi::rule<Iterator, format_data()> format;
+ qi::rule<Iterator, char()> flags;
+ qi::rule<Iterator, char()> fill;
+ qi::rule<Iterator, int()> width;
+ qi::rule<Iterator, int()> prec;
+ qi::rule<Iterator, char()> type;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// real_policies implementation allowing to use a printf style format
+// specification for Karma floating pointing number generators
+template <typename T>
+struct format_policies : karma::real_policies<T>
+{
+ typedef karma::real_policies<T> base_policy_type;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // This real_policies implementation requires the output_iterator to
+ // implement buffering and character counting. This needs to be reflected
+ // in the properties exposed by the generator
+ typedef boost::mpl::int_<
+ karma::generator_properties::countingbuffer
+ > properties;
+
+ ///////////////////////////////////////////////////////////////////////////
+ format_policies(char const* fmt = "%f")
+ {
+ char const* last = fmt;
+ while (*last)
+ last++;
+
+ client::format_grammar<char const*> g;
+ if (!qi::parse(fmt, last, g, format_))
+ throw std::runtime_error("bad format string");
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // returns the overall format: scientific or fixed
+ int floatfield(T n) const
+ {
+ if (format_.type == 'e' || format_.type == 'E')
+ return base_policy_type::fmtflags::scientific;
+
+ if (format_.type == 'f')
+ return base_policy_type::fmtflags::fixed;
+
+ BOOST_ASSERT(format_.type == 'g' || format_.type == 'G');
+ return this->base_policy_type::floatfield(n);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // returns whether to emit a sign even for non-negative numbers
+ bool const force_sign(T) const
+ {
+ return format_.flag == '+';
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // returns the number of required digits for the fractional part
+ unsigned precision(T) const
+ {
+ return format_.precision;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // emit the decimal dot
+ template <typename OutputIterator>
+ static bool dot (OutputIterator& sink, T n, unsigned precision)
+ {
+ // don't print the dot if no fractional digits are to be emitted
+ if (precision == 0)
+ return true;
+ return base_policy_type::dot(sink, n, precision);
+ }
+
+ template <typename CharEncoding, typename Tag, typename OutputIterator>
+ bool exponent (OutputIterator& sink, long n) const
+ {
+ if (format_.type == 'E' || format_.type == 'G') {
+ // print exponent symbol in upper case
+ return this->base_policy_type::
+ template exponent<char_encoding::ascii, tag::upper>(sink, n);
+ }
+ return this->base_policy_type::
+ template exponent<CharEncoding, Tag>(sink, n);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // this gets called by the numeric generators at the top level, it allows
+ // to do alignment and other high level things
+ template <typename Inserter, typename OutputIterator, typename Policies>
+ bool call (OutputIterator& sink, T n, Policies const& p) const
+ {
+ bool r = false;
+ if (format_.flag == '-') { // left align
+ // wrap the given output iterator to allow counting
+ karma::detail::enable_counting<OutputIterator> counting(sink);
+
+ // first generate the actual floating point number
+ r = Inserter::call_n(sink, n, p);
+
+ // pad the output until the max width is reached
+ while(r && int(counting.count()) < format_.width)
+ r = karma::generate(sink, ' ');
+ }
+ else { // right align
+ // wrap the given output iterator to allow left padding
+ karma::detail::enable_buffering<OutputIterator> buffering(
+ sink, format_.width);
+
+ // first generate the actual floating point number
+ {
+ karma::detail::disable_counting<OutputIterator> nocounting(sink);
+ r = Inserter::call_n(sink, n, p);
+ }
+
+ buffering.disable(); // do not perform buffering any more
+
+ // generate the left padding
+ karma::detail::enable_counting<OutputIterator> counting(
+ sink, buffering.buffer_size());
+ while(r && int(counting.count()) < format_.width)
+ r = karma::generate(sink, format_.fill);
+
+ // copy the buffered output to the target output iterator
+ if (r)
+ buffering.buffer_copy();
+ }
+ return r;
+ }
+
+ client::format_data format_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// This is the generator usable in any Karma output format expression, it needs
+// to be utilized as
+//
+// generate(sink, real("%6.3f"), 3.1415926536); // prints: ' 3.142'
+//
+// and it supports the format specification as described above.
+typedef karma::real_generator<double, format_policies<double> > real;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////////\n\n";
+ std::cout << "A format driven floating point number generator for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a printf style format\n";
+ std::cout << "Type [enter] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+
+ try {
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+ if (!karma::generate(sink, real(str.c_str()), 4*std::atan(1.0)))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << ">" << generated << "<\n";
+ }
+ }
+ catch (std::runtime_error const&) {
+ std::cout << "-------------------------\n";
+ std::cout << "Invalid format specified!\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/quick_start1.cpp b/src/boost/libs/spirit/example/karma/quick_start1.cpp
new file mode 100644
index 00000000..4a99b95c
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/quick_start1.cpp
@@ -0,0 +1,119 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The main purpose of this example is to show how a single container type can
+// be formatted using different output grammars.
+
+#include <boost/config/warning_disable.hpp>
+#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;
+
+///////////////////////////////////////////////////////////////////////////////
+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 delimited list" << std::endl;
+ std::cout <<
+ karma::format_delimited(
+ *int_, // format description
+ space, // delimiter
+ v // data
+ ) << std::endl << std::endl;
+
+ std::cout <<
+ karma::format_delimited(
+ '[' << *int_ << ']', // format description
+ space, // delimiter
+ v // data
+ ) << 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
+ '\n', // delimiter
+ v // data
+ ) << 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
+ '\n', // delimiter
+ v // data
+ ) << std::endl;
+
+ std::cout << std::endl;
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/quoted_strings.cpp b/src/boost/libs/spirit/example/karma/quoted_strings.cpp
new file mode 100644
index 00000000..ecbdd969
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/quoted_strings.cpp
@@ -0,0 +1,70 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to demonstrate how to utilize alternatives
+// and the built in matching capabilities of Karma generators to emit output
+// in different formats based on the content of an attribute (not its type).
+
+#include <boost/config/warning_disable.hpp>
+
+#include <string>
+#include <vector>
+
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+namespace client
+{
+ namespace karma = boost::spirit::karma;
+ namespace phx = boost::phoenix;
+
+ template <typename OutputIterator>
+ struct quoted_strings
+ : karma::grammar<OutputIterator, std::vector<std::string>()>
+ {
+ quoted_strings()
+ : quoted_strings::base_type(strings)
+ {
+ strings = (bareword | qstring) % ' ';
+ bareword = karma::repeat(phx::size(karma::_val))
+ [ karma::alnum | karma::char_("-.,_$") ];
+ qstring = '"' << karma::string << '"';
+ }
+
+ karma::rule<OutputIterator, std::vector<std::string>()> strings;
+ karma::rule<OutputIterator, std::string()> bareword, qstring;
+ };
+}
+
+int main()
+{
+ namespace karma = boost::spirit::karma;
+
+ typedef std::back_insert_iterator<std::string> sink_type;
+
+ std::string generated;
+ sink_type sink(generated);
+
+ std::vector<std::string> v;
+ v.push_back("foo");
+ v.push_back("bar baz");
+ v.push_back("hello");
+
+ client::quoted_strings<sink_type> g;
+ if (!karma::generate(sink, g, v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generating failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Generated: " << generated << "\n";
+ std::cout << "-------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/karma/reference.cpp b/src/boost/libs/spirit/example/karma/reference.cpp
new file mode 100644
index 00000000..dd11f26e
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/reference.cpp
@@ -0,0 +1,911 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+
+//[reference_karma_includes
+#include <boost/spirit/include/karma.hpp>
+#include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+#include <iostream>
+#include <string>
+//]
+
+//[reference_karma_includes_simple
+#include <boost/spirit/include/karma.hpp>
+#include <iostream>
+#include <string>
+//]
+
+//[reference_karma_output_iterator
+typedef std::back_insert_iterator<std::string> output_iterator_type;
+//]
+
+//[reference_karma_test
+template <typename G>
+void test_generator(char const* expected, G const& g)
+{
+ std::string s;
+ std::back_insert_iterator<std::string> out(s);
+ if (boost::spirit::karma::generate(out, g) && s == expected)
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_karma_test_attr
+template <typename G, typename T>
+void test_generator_attr(char const* expected, G const& g, T const& attr)
+{
+ std::string s;
+ std::back_insert_iterator<std::string> out(s);
+ if (boost::spirit::karma::generate(out, g, attr) && s == expected)
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_karma_test_attr2
+template <typename G, typename T1, typename T2>
+void test_generator_attr(char const* expected, G const& g, T1 const& attr1,
+ T2 const& attr2)
+{
+ std::string s;
+ std::back_insert_iterator<std::string> out(s);
+ if (boost::spirit::karma::generate(out, g, attr1, attr2) && s == expected)
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_karma_test_attr_delim
+template <typename G, typename Delimiter, typename T>
+void test_generator_attr_delim(char const* expected, G const& g, Delimiter const& d, T const& attr)
+{
+ std::string s;
+ std::back_insert_iterator<std::string> out(s);
+ if (boost::spirit::karma::generate_delimited(out, g, d, attr) && s == expected)
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_karma_binary_test
+template <typename G>
+void test_binary_generator(char const* expected, std::size_t size, G const& g)
+{
+ std::string s;
+ std::back_insert_iterator<std::string> out(s);
+ if (boost::spirit::karma::generate(out, g) && !std::memcmp(s.c_str(), expected, size))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_karma_binary_test_attr
+template <typename G, typename T>
+void test_binary_generator_attr(char const* expected, std::size_t size, G const& g, T const& attr)
+{
+ std::string s;
+ std::back_insert_iterator<std::string> out(s);
+ if (boost::spirit::karma::generate(out, g, attr) && !std::memcmp(s.c_str(), expected, size))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_karma_complex
+// a simple complex number representation z = a + bi
+struct complex
+{
+ complex (double a, double b)
+ : a(a), b(b)
+ {}
+
+ double a;
+ double b;
+};
+//]
+
+//[reference_karma_stream_complex
+// define streaming operator for the type complex
+std::ostream&
+operator<< (std::ostream& os, complex const& z)
+{
+ os << "{" << z.a << "," << z.b << "}";
+ return os;
+}
+//]
+
+//[reference_karma_auto_complex
+/*`The following construct is required to allow the `complex` data structure
+ to be utilized as a __fusion__ sequence. This is required as we will
+ emit output for this data structure with a __karma__ sequence:
+ `'{' << karma::double_ << ',' << karma::double_ << '}'`.
+*/
+BOOST_FUSION_ADAPT_STRUCT(
+ complex,
+ (double, a)
+ (double, b)
+)
+
+/*`We add a specialization for the create_generator customization point
+ defining a custom output format for the complex type. Generally, any
+ specialization for create_generator is expected to return the proto
+ expression to be used to generate output for the type the customization
+ point has been specialized for.
+ */
+/*`We need to utilize `proto::deep_copy` as the expression contains literals
+ (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto
+ expression by reference only. The deep copy converts the proto tree to
+ hold this by value. The deep copy operation can be left out for simpler
+ proto expressions (not containing references to temporaries). Alternatively
+ you could use the `proto::make_expr` facility to build the required
+ proto expression.
+*/
+namespace boost { namespace spirit { namespace traits
+{
+ template <>
+ struct create_generator<complex>
+ {
+ typedef proto::result_of::deep_copy<
+ BOOST_TYPEOF('{' << karma::double_ << ',' << karma::double_ << '}')
+ >::type type;
+
+ static type call()
+ {
+ return proto::deep_copy(
+ '{' << karma::double_ << ',' << karma::double_ << '}');
+ }
+ };
+}}}
+//]
+
+//[reference_karma_auxiliary_attr_cast_data1
+// this is just a test structure we want to use in place of an int
+struct int_data
+{
+ int i;
+};
+
+// we provide a custom attribute transformation to allow its use as an int
+namespace boost { namespace spirit { namespace traits
+{
+ template <>
+ struct transform_attribute<int_data const, int, karma::domain>
+ {
+ typedef int type;
+ static int pre(int_data const& d) { return d.i; }
+ };
+}}}
+//]
+
+namespace client
+{
+ using boost::spirit::karma::grammar;
+ using boost::spirit::karma::rule;
+ using boost::spirit::ascii::space_type;
+
+ //[karma_reference_grammar_definition
+ /*`Basic grammar usage:
+ */
+ struct num_list : grammar<output_iterator_type, space_type, std::vector<int>()>
+ {
+ num_list() : base_type(start)
+ {
+ using boost::spirit::int_;
+ num = int_;
+ start = num << *(',' << num);
+ }
+
+ rule<output_iterator_type, space_type, std::vector<int>()> start;
+ rule<output_iterator_type, space_type, int()> num;
+ };
+ //]
+}
+
+int main()
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Operators
+ ///////////////////////////////////////////////////////////////////////////
+ {
+ //[reference_karma_using_declarations_sequence
+ using boost::spirit::karma::double_;
+ //]
+
+ //[reference_karma_sequence
+ test_generator_attr("1.0,2.0", double_ << ',' << double_, std::make_pair(1.0, 2.0));
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_alternative
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::ascii::string;
+ //]
+
+ //[reference_karma_alternative1
+ boost::variant<std::string, double> v1(1.0);
+ test_generator_attr("1.0", string | double_, v1);
+ test_generator_attr("2.0", string | double_, 2.0);
+ //]
+
+ //[reference_karma_alternative2
+ boost::variant<std::string, double> v2("example");
+ test_generator_attr("example", string | double_, v2);
+ test_generator_attr("example", string | double_, "example");
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_kleene
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::space;
+ //]
+
+ //[reference_karma_kleene
+ std::vector<double> v;
+ v.push_back(1.0);
+ v.push_back(2.0);
+ v.push_back(3.0);
+ test_generator_attr_delim("1.0 2.0 3.0 ", *double_, space, v);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_plus
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::space;
+ //]
+
+ //[reference_karma_plus1
+ std::vector<double> v1;
+ v1.push_back(1.0);
+ v1.push_back(2.0);
+ v1.push_back(3.0);
+ test_generator_attr_delim("1.0 2.0 3.0 ", +double_, space, v1);
+ //]
+
+ //[reference_karma_plus2
+ std::vector<double> v2; // empty container
+ test_generator_attr("empty", +double_ | "empty", v2);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_list
+ using boost::spirit::karma::double_;
+ //]
+
+ //[reference_karma_list
+ std::vector<double> v1;
+ v1.push_back(1.0);
+ test_generator_attr("1.0", double_ % ',', v1);
+
+ v1.push_back(2.0);
+ test_generator_attr("1.0,2.0", double_ % ',', v1);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_optional
+ using boost::spirit::karma::double_;
+ //]
+
+ //[reference_karma_optional1
+ boost::optional<double> val(1.0);
+ test_generator_attr("1.0", -double_, val);
+ test_generator_attr("2.0", -double_, 2.0);
+ //]
+ }
+ {
+ using boost::spirit::karma::double_;
+
+ //[reference_karma_optional2
+ boost::optional<double> val; // empty optional
+ test_generator_attr("", -double_, val);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_and_predicate
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::ascii::char_;
+ using boost::spirit::karma::ascii::string;
+ using boost::phoenix::ref;
+ //]
+
+ //[reference_karma_and_predicate
+ test_generator_attr("b", &char_('a') << 'b' | 'c', 'a');
+ test_generator_attr("c", &char_('a') << 'b' | 'c', 'x');
+
+ test_generator_attr("abc", &string("123") << "abc" | "def", "123");
+ test_generator_attr("def", &string("123") << "abc" | "def", "456");
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_not_predicate
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::ascii::char_;
+ using boost::spirit::karma::ascii::string;
+ using boost::phoenix::ref;
+ //]
+
+ //[reference_karma_not_predicate
+ test_generator_attr("c", !char_('a') << 'b' | 'c', 'a');
+ test_generator_attr("b", !char_('a') << 'b' | 'c', 'x');
+
+ test_generator_attr("def", !string("123") << "abc" | "def", "123");
+ test_generator_attr("abc", !string("123") << "abc" | "def", "456");
+ //]
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Directives
+ ///////////////////////////////////////////////////////////////////////////
+ {
+ //[reference_karma_using_declarations_alignment
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::left_align;
+ using boost::spirit::karma::center;
+ using boost::spirit::karma::right_align;
+ //]
+
+ //[reference_karma_alignment
+ std::pair<double, double> p (1.0, 2.0);
+ test_generator_attr("1.0 |2.0", left_align(8)[double_] << '|' << double_, p);
+ test_generator_attr(" 1.0 |2.0", center(8)[double_] << '|' << double_, p);
+ test_generator_attr(" 1.0|2.0", right_align(8)[double_] << '|' << double_, p);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_repeat
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::repeat;
+ //]
+
+ //[reference_karma_repeat
+ std::vector<double> v;
+ v.push_back(1.0);
+ v.push_back(2.0);
+ v.push_back(3.0);
+
+ test_generator_attr("[1.0][2.0][3.0]", repeat['[' << double_ << ']'], v);
+ test_generator_attr("[1.0][2.0]", repeat(2)['[' << double_ << ']'], v);
+
+ // fails because of insufficient number of items
+ test_generator_attr("", repeat(4)['[' << double_ << ']'], v);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_delimit
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::delimit;
+ using boost::spirit::karma::verbatim;
+ //]
+
+ //[reference_karma_delimit
+ test_generator_attr("[ 2.0 , 4.3 ] ",
+ delimit['[' << double_ << ',' << double_ << ']'], 2.0, 4.3);
+ test_generator_attr("[*2.0*,*4.3*]*",
+ delimit('*')['[' << double_ << ',' << double_ << ']'], 2.0, 4.3);
+ test_generator_attr("[2.0, 4.3 ] ",
+ delimit[verbatim['[' << double_ << ','] << double_ << ']'], 2.0, 4.3);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_upperlower
+ using boost::spirit::karma::double_;
+ using boost::spirit::ascii::upper;
+ using boost::spirit::ascii::lower;
+ //]
+
+ //[reference_karma_upperlower
+ test_generator_attr("abc:2.0e-06", lower["ABC:" << double_], 2e-6);
+ test_generator_attr("ABC:2.0E-06", upper["abc:" << double_], 2e-6);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_maxwidth
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::maxwidth;
+ using boost::spirit::karma::left_align;
+ using boost::spirit::karma::right_align;
+ //]
+
+ //[reference_karma_maxwidth
+ test_generator("01234", maxwidth(5)["0123456789"]);
+ test_generator(" 012", maxwidth(5)[right_align(12)["0123456789"]]);
+ test_generator("0123 ", maxwidth(8)[left_align(8)["0123"]]);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_buffer
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::buffer;
+ //]
+
+ //[reference_karma_buffer
+ std::vector<double> v; // empty container
+ test_generator_attr("", -buffer['[' << +double_ << ']'], v);
+
+ v.push_back(1.0); // now, fill the container
+ v.push_back(2.0);
+ test_generator_attr("[1.02.0]", buffer['[' << +double_ << ']'], v);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_omit
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::omit;
+ //]
+
+ //[reference_karma_omit
+ std::pair<double, double> p (1.0, 2.0);
+ test_generator_attr("2.0", omit[double_] << double_, p);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_duplicate
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::duplicate;
+ using boost::spirit::karma::space;
+ //]
+
+ //[reference_karma_duplicate
+ test_generator_attr("2.02.0", duplicate[double_ << double_], 2.0);
+ test_generator_attr_delim("2.0 2.0 ", duplicate[double_ << double_], space, 2.0);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_columns
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::columns;
+ using boost::spirit::karma::space;
+ //]
+
+ //[reference_karma_columns
+ std::vector<double> v;
+ v.push_back(1.0);
+ v.push_back(2.0);
+ v.push_back(3.0);
+ test_generator_attr("1.0\n2.0\n3.0\n", columns(1)[*double_], v);
+ test_generator_attr_delim("1.0 2.0 \n3.0 \n", columns(2)[*double_], space, v);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_bool
+ using boost::spirit::karma::bool_;
+ using boost::spirit::karma::lit;
+ //]
+
+ //[reference_karma_bool
+ test_generator("true", lit(true));
+ test_generator("false", bool_(false));
+ test_generator_attr("true", bool_(true), true);
+ test_generator_attr("", bool_(true), false); // fails (as true != false)!
+ test_generator_attr("false", bool_, false);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_int
+ using boost::spirit::karma::int_;
+ using boost::spirit::karma::lit;
+ //]
+
+ //[reference_karma_int
+ test_generator("-2", lit(-2));
+ test_generator("-2", int_(-2));
+ test_generator_attr("-2", int_(-2), -2);
+ test_generator_attr("", int_(-2), 3); // fails (as -2 != 3)!
+ test_generator_attr("-2", int_, -2);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_uint
+ using boost::spirit::karma::uint_;
+ using boost::spirit::karma::lit;
+ //]
+
+ //[reference_karma_uint
+ test_generator("2", lit(2U));
+ test_generator("2", uint_(2));
+ test_generator_attr("2", uint_(2), 2);
+ test_generator_attr("", uint_(2), 3); // fails (as 2 != 3)!
+ test_generator_attr("2", uint_, 2);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_real
+ using boost::spirit::karma::double_;
+ using boost::spirit::karma::lit;
+ //]
+
+ //[reference_karma_real
+ test_generator("2.0", lit(2.0));
+ test_generator("2.0", double_(2));
+ test_generator_attr("2.0", double_(2.0), 2.0);
+ test_generator_attr("", double_(2.0), 3.0); // fails (as 2.0 != 3.0)!
+ test_generator_attr("-2.0", double_, -2.0);
+
+ test_generator_attr("1.234e05", double_, 1234.0e2);
+ test_generator_attr("1.234e-06", double_, 0.000001234);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_char
+ using boost::spirit::karma::lit;
+ using boost::spirit::ascii::char_;
+ //]
+
+ //[reference_karma_char
+ test_generator("A", 'A');
+ test_generator("A", lit('A'));
+
+ test_generator_attr("a", char_, 'a');
+ test_generator("A", char_('A'));
+ test_generator_attr("A", char_('A'), 'A');
+ test_generator_attr("", char_('A'), 'B'); // fails (as 'A' != 'B')
+
+ test_generator_attr("A", char_('A', 'Z'), 'A');
+ test_generator_attr("", char_('A', 'Z'), 'a'); // fails (as 'a' does not belong to 'A'...'Z')
+
+ test_generator_attr("k", char_("a-z0-9"), 'k');
+ test_generator_attr("", char_("a-z0-9"), 'A'); // fails (as 'A' does not belong to "a-z0-9")
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_char_class
+ using boost::spirit::karma::alpha;
+ using boost::spirit::karma::upper;
+ //]
+
+ //[reference_karma_char_class
+ test_generator_attr("a", alpha, 'a');
+ test_generator_attr("A", alpha, 'A');
+ test_generator_attr("", alpha, '1'); // fails (as isalpha('1') is false)
+ test_generator_attr("A", upper[alpha], 'A');
+ test_generator_attr("", upper[alpha], 'a'); // fails (as isupper('a') is false)
+ //]
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // string
+ {
+ //[reference_karma_using_declarations_string
+ using boost::spirit::karma::lit;
+ using boost::spirit::ascii::string;
+ //]
+
+ //[reference_karma_string
+ test_generator("abc", "abc");
+ test_generator("abc", lit("abc"));
+ test_generator("abc", lit(std::string("abc")));
+
+ test_generator_attr("abc", string, "abc");
+ test_generator("abc", string("abc"));
+ test_generator("abc", string(std::string("abc")));
+
+ test_generator_attr("abc", string("abc"), "abc");
+ test_generator_attr("", string("abc"), "cba"); // fails (as "abc" != "cba")
+ //]
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // auxiliary
+ {
+ //[reference_karma_using_declarations_eol
+ using boost::spirit::karma::eol;
+ //]
+
+ //[reference_karma_eol
+ test_generator("\n", eol);
+ test_generator("abc\n", "abc" << eol);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_attr_cast
+ using boost::spirit::karma::int_;
+ //]
+
+ //[reference_karma_attr_cast1
+ int_data d = { 1 };
+ test_generator_attr("1", boost::spirit::karma::attr_cast(int_), d);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_eps
+ using boost::spirit::karma::eps;
+ using boost::phoenix::val;
+ //]
+
+ //[reference_karma_eps
+ test_generator("abc", eps[std::cout << val("starting eps example")] << "abc");
+ test_generator("abc", eps(true) << "abc");
+ test_generator("", eps(false) << "abc"); // fails as eps expression is 'false'
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_lazy
+ namespace karma = boost::spirit::karma;
+ using boost::spirit::karma::_1;
+ using boost::spirit::ascii::string;
+ using boost::phoenix::val;
+ //]
+
+ //[reference_karma_lazy
+ test_generator_attr("abc", karma::lazy(val(string)), "abc");
+ test_generator("abc", karma::lazy(val(string))[_1 = "abc"]);
+ //]
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // stream module
+ {
+ //[reference_karma_using_declarations_stream
+ using boost::spirit::karma::stream;
+ //]
+
+ //[reference_karma_stream
+ test_generator_attr("abc", stream, "abc");
+ test_generator("abc", stream("abc"));
+ test_generator_attr("{1.2,2.4}", stream, complex(1.2, 2.4));
+ test_generator("{1.2,2.4}", stream(complex(1.2, 2.4)));
+ //]
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // auto module
+ {
+ //[reference_karma_using_declarations_auto
+ using boost::spirit::karma::auto_;
+ //]
+
+ //[reference_karma_auto
+ /*`Emit a simple string using the `karma::string` generator:
+ */
+ test_generator_attr("abc", auto_, "abc");
+ test_generator("abc", auto_("abc"));
+
+ /*`Emit instances of the `complex` data type as defined above using the
+ generator defined by the customization point for `complex`:
+ */
+ test_generator_attr("{1.2,2.4}", auto_, complex(1.2, 2.4));
+ test_generator("{1.2,2.4}", auto_(complex(1.2, 2.4)));
+ //]
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // binary module
+ {
+ //[reference_karma_using_declarations_native_binary
+ using boost::spirit::karma::byte_;
+ using boost::spirit::karma::word;
+ using boost::spirit::karma::dword;
+ using boost::spirit::karma::qword;
+ //]
+
+ //[reference_karma_native_binary_little
+ test_binary_generator("\x01", 1, byte_(0x01));
+ test_binary_generator("\x01\x02", 2, word(0x0201));
+ test_binary_generator("\x01\x02\x03\x04", 4, dword(0x04030201));
+ test_binary_generator("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword(0x0807060504030201LL));
+
+ test_binary_generator_attr("\x01", 1, byte_, 0x01);
+ test_binary_generator_attr("\x01\x02", 2, word, 0x0201);
+ test_binary_generator_attr("\x01\x02\x03\x04", 4, dword, 0x04030201);
+ test_binary_generator_attr("\x01\x02\x03\x04\x05\x06\x07\x08", 8, qword, 0x0807060504030201LL);
+ //]
+
+ //[reference_karma_native_binary_big
+ test_binary_generator("\x01", 1, byte_(0x01));
+ test_binary_generator("\x02\x01", 2, word(0x0201));
+ test_binary_generator("\x04\x03\x02\x01", 4, dword(0x04030201));
+ test_binary_generator("\x08\x07\x06\x05\x04\x03\x02\x01", 8, qword(0x0807060504030201LL));
+
+ test_binary_generator_attr("\x01", 1, byte_, 0x01);
+ test_binary_generator_attr("\x02\x01", 2, word, 0x0201);
+ test_binary_generator_attr("\x04\x03\x02\x01", 4, dword, 0x04030201);
+ test_binary_generator_attr("\x08\x07\x06\x05\x04\x03\x02\x01", 8, qword, 0x0807060504030201LL);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_little_binary
+ using boost::spirit::karma::little_word;
+ using boost::spirit::karma::little_dword;
+ using boost::spirit::karma::little_qword;
+ //]
+
+ //[reference_karma_little_binary
+ test_binary_generator("\x01\x02", 2, little_word(0x0201));
+ test_binary_generator("\x01\x02\x03\x04", 4, little_dword(0x04030201));
+ test_binary_generator("\x01\x02\x03\x04\x05\x06\x07\x08", 8, little_qword(0x0807060504030201LL));
+
+ test_binary_generator_attr("\x01\x02", 2, little_word, 0x0201);
+ test_binary_generator_attr("\x01\x02\x03\x04", 4, little_dword, 0x04030201);
+ test_binary_generator_attr("\x01\x02\x03\x04\x05\x06\x07\x08", 8, little_qword, 0x0807060504030201LL);
+ //]
+ }
+
+ {
+ //[reference_karma_using_declarations_big_binary
+ using boost::spirit::karma::big_word;
+ using boost::spirit::karma::big_dword;
+ using boost::spirit::karma::big_qword;
+ //]
+
+ //[reference_karma_big_binary
+ test_binary_generator("\x02\x01", 2, big_word(0x0201));
+ test_binary_generator("\x04\x03\x02\x01", 4, big_dword(0x04030201));
+ test_binary_generator("\x08\x07\x06\x05\x04\x03\x02\x01", 8, big_qword(0x0807060504030201LL));
+
+ test_binary_generator_attr("\x02\x01", 2, big_word, 0x0201);
+ test_binary_generator_attr("\x04\x03\x02\x01", 4, big_dword, 0x04030201);
+ test_binary_generator_attr("\x08\x07\x06\x05\x04\x03\x02\x01", 8, big_qword, 0x0807060504030201LL);
+ //]
+ }
+
+ // action
+ {
+ //[reference_karma_using_declarations_action
+ using boost::spirit::karma::int_;
+ using boost::spirit::karma::string;
+ using boost::spirit::karma::_1;
+ using boost::phoenix::ref;
+ using boost::phoenix::val;
+ //]
+
+ //[reference_karma_action
+ int i = 42;
+ test_generator("42", int_[_1 = ref(i)]);
+ test_generator("abc", string[_1 = val("abc")]);
+ //]
+ }
+
+ // rule
+ {
+ //[karma_reference_rule
+ //`Some using declarations:
+ using boost::spirit::karma::rule;
+ using boost::spirit::karma::int_;
+ using boost::spirit::ascii::space;
+ using boost::spirit::ascii::space_type;
+
+ /*`Basic rule:
+ */
+ rule<output_iterator_type> r;
+ r = int_(123);
+ test_generator("123", r);
+
+ /*`Rule with consumed attribute:
+ */
+ rule<output_iterator_type, int()> ra;
+ ra = int_;
+ test_generator_attr("123", ra, 123);
+
+ /*`Rule with delimiter and consumed attribute:
+ */
+ rule<output_iterator_type, std::vector<int>(), space_type> rs;
+ rs = *int_;
+ std::vector<int> v;
+ v.push_back(123);
+ v.push_back(456);
+ v.push_back(789);
+ test_generator_attr_delim("123 456 789", rs, space, v);
+ //]
+ }
+
+ // grammar
+ {
+ using client::num_list;
+
+ //[karma_reference_grammar_using
+ //`Some using declarations:
+ using boost::spirit::ascii::space_type;
+ using boost::spirit::ascii::space;
+ using boost::spirit::int_;
+ using boost::spirit::karma::grammar;
+ using boost::spirit::karma::rule;
+ //]
+
+ //[karma_reference_grammar
+ //`How to use the example grammar:
+ num_list nlist;
+ std::vector<int> v;
+ v.push_back(123);
+ v.push_back(456);
+ v.push_back(789);
+ test_generator_attr_delim("123 , 456 , 789", nlist, space, v);
+ //]
+ }
+
+ // symbols
+ {
+ //[reference_karma_using_declarations_symbols
+ using boost::spirit::karma::symbols;
+ //]
+
+ //[reference_karma_symbols
+ symbols<char, char const*> sym;
+
+ sym.add
+ ('a', "Apple")
+ ('b', "Banana")
+ ('o', "Orange")
+ ;
+
+ test_generator_attr("Banana", sym, 'b');
+ //]
+ }
+
+ // as
+ {
+ //[reference_karma_using_declarations_as
+ using boost::spirit::utree;
+ using boost::spirit::utree_type;
+ using boost::spirit::utf8_symbol_type;
+ using boost::spirit::karma::as;
+ using boost::spirit::karma::as_string;
+ using boost::spirit::karma::char_;
+ using boost::spirit::karma::double_;
+ //]
+
+ //[reference_karma_as
+ /*`To properly handle string concatenation with __utree__, we
+ make use of `as_string[]`. We also use `as<T>` to explicitly extract
+ a __utree__ symbol node.*/
+
+ typedef as<utf8_symbol_type> as_symbol_type;
+ as_symbol_type const as_symbol = as_symbol_type();
+
+ utree ut;
+ ut.push_back("xyz");
+ ut.push_back(1.23);
+
+ test_generator_attr("xyz1.23", as_string[*char_] << double_, ut);
+ test_generator_attr("xyz1.23", as<std::string>()[*char_] << double_, ut);
+
+ ut.clear();
+
+ ut.push_back(utf8_symbol_type("xyz"));
+ ut.push_back(1.23);
+
+ test_generator_attr("xyz1.23", as_symbol[*char_] << double_, ut);
+ test_generator_attr("xyz1.23", as<utf8_symbol_type>()[*char_] << double_, ut);
+ //]
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/reorder_struct.cpp b/src/boost/libs/spirit/example/karma/reorder_struct.cpp
new file mode 100644
index 00000000..8e5b0149
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/reorder_struct.cpp
@@ -0,0 +1,105 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The main purpose of this example is to show how a single fusion sequence
+// can be used to generate output of the elements in different sequences
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/karma.hpp>
+#include <boost/fusion/include/struct.hpp>
+#include <boost/fusion/include/nview.hpp>
+#include <boost/assign/std/vector.hpp>
+
+namespace fusion = boost::fusion;
+namespace karma = boost::spirit::karma;
+
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ // Our employee struct
+ struct employee
+ {
+ std::string surname;
+ std::string forename;
+ int age;
+ double salary;
+ std::string department;
+ };
+
+ // define iterator type
+ typedef std::back_insert_iterator<std::string> iterator_type;
+
+ // This is the output routine taking a format description and the data to
+ // print
+ template <typename Generator, typename Sequence>
+ void generate(Generator const& g, Sequence const& s)
+ {
+ std::string generated;
+ iterator_type sink(generated);
+ karma::generate(sink, g, s);
+ std::cout << generated << std::endl;
+ }
+}
+
+// We need to tell fusion about our employee struct to make it a first-class
+// fusion citizen. This has to be in global scope. Note that we don't need to
+// list the members of our struct in the same sequence a they are defined
+BOOST_FUSION_ADAPT_STRUCT(
+ client::employee,
+ (int, age)
+ (std::string, surname)
+ (std::string, forename)
+ (std::string, department)
+ (double, salary)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::string str;
+
+ // some employees
+ client::employee john = { "John", "Smith", 25, 2000.50, "Sales" };
+ client::employee mary = { "Mary", "Higgins", 23, 2200.36, "Marketing" };
+ client::employee tom = { "Tom", "Taylor", 48, 3200.00, "Boss" };
+
+ // print data about employees in different formats
+ {
+ // print forename and age
+ client::generate(
+ karma::string << ", " << karma::int_,
+ fusion::as_nview<2, 0>(john));
+
+ // print surname, forename, and salary
+ client::generate(
+ karma::string << ' ' << karma::string << ": " << karma::double_,
+ fusion::as_nview<1, 2, 4>(mary));
+
+ // print forename, age, and department
+ client::generate(
+ karma::string << ": " << karma::int_ << " (" << karma::string << ')',
+ fusion::as_nview<2, 0, 3>(tom));
+ }
+
+ // now make a list of all employees and print them all
+ std::vector<client::employee> employees;
+ {
+ using namespace boost::assign;
+ employees += john, mary, tom;
+ }
+
+ // print surname, forename, and salary for all employees
+ {
+ typedef
+ fusion::result_of::as_nview<client::employee const, 1, 2, 4>::type
+ names_and_salary;
+
+ karma::rule<client::iterator_type, names_and_salary()> r =
+ karma::string << ' ' << karma::string << ": " << karma::double_;
+
+ client::generate(r % karma::eol, employees);
+ }
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/simple_columns_directive.cpp b/src/boost/libs/spirit/example/karma/simple_columns_directive.cpp
new file mode 100644
index 00000000..3a5348af
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/simple_columns_directive.cpp
@@ -0,0 +1,49 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how a simple custom generator
+// directive can be written. We develop a custom generator allowing to wrap
+// the generated output after each 5th column.
+//
+// For more information see: http://boost-spirit.com/home/?page_id=659
+
+#include <boost/spirit/include/karma_generate_attr.hpp>
+#include <boost/spirit/include/karma_char.hpp>
+#include <boost/spirit/include/karma_operator.hpp>
+#include <boost/spirit/include/karma_numeric.hpp>
+
+#include <string>
+#include "simple_columns_directive.hpp"
+
+namespace karma = boost::spirit::karma;
+
+int main()
+{
+ using custom_generator::columns;
+
+ std::vector<int> v;
+ for (int i = 0; i < 17; ++i)
+ v.push_back(i);
+
+ std::string generated;
+ std::back_insert_iterator<std::string> sink(generated);
+
+ bool result = karma::generate_delimited(
+ sink, columns[*karma::int_], karma::space, v);
+ if (result)
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Generation succeeded\n";
+ std::cout << "generated output: " << "\n" << generated << "\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Generation failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/karma/simple_columns_directive.hpp b/src/boost/libs/spirit/example/karma/simple_columns_directive.hpp
new file mode 100644
index 00000000..56403f33
--- /dev/null
+++ b/src/boost/libs/spirit/example/karma/simple_columns_directive.hpp
@@ -0,0 +1,133 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(COLUMNS_DEC_05_2009_0716PM)
+#define COLUMNS_DEC_05_2009_0716PM
+
+#include <boost/spirit/include/karma_generate.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// definition the place holder
+namespace custom_generator
+{
+ BOOST_SPIRIT_TERMINAL(columns)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// implementation the enabler
+namespace boost { namespace spirit
+{
+ // We want custom_generator::columns to be usable as a directive only,
+ // and only for generator expressions (karma::domain).
+ template <>
+ struct use_directive<karma::domain, custom_generator::tag::columns>
+ : mpl::true_ {};
+}}
+
+///////////////////////////////////////////////////////////////////////////////
+// implementation of the generator
+namespace custom_generator
+{
+ // special delimiter wrapping the original one while additionally emitting
+ // the column delimiter after each 5th invocation
+ template <typename Delimiter>
+ struct columns_delimiter
+ {
+ columns_delimiter(Delimiter const& delim)
+ : delimiter(delim), count(0) {}
+
+ // This function is called during the actual delimiter output
+ template <typename OutputIterator, typename Context
+ , typename Delimiter_, typename Attribute>
+ bool generate(OutputIterator& sink, Context&, Delimiter_ const&
+ , Attribute const&) const
+ {
+ // first invoke the wrapped delimiter
+ if (!karma::delimit_out(sink, delimiter))
+ return false;
+
+ // now we count the number of invocations and emit the column
+ // delimiter after each 5th column
+ if ((++count % 5) == 0)
+ *sink++ = '\n';
+ return true;
+ }
+
+ // Generate a final column delimiter if the last invocation didn't
+ // emit one
+ template <typename OutputIterator>
+ bool final_delimit_out(OutputIterator& sink) const
+ {
+ if (count % 5)
+ *sink++ = '\n';
+ return true;
+ }
+
+ Delimiter const& delimiter; // wrapped delimiter
+ mutable unsigned int count; // invocation counter
+ };
+
+ // That's the actual columns generator
+ template <typename Subject>
+ struct simple_columns_generator
+ : boost::spirit::karma::unary_generator<
+ simple_columns_generator<Subject> >
+ {
+ // Define required output iterator properties
+ typedef typename Subject::properties properties;
+
+ // Define the attribute type exposed by this parser component
+ template <typename Context, typename Iterator>
+ struct attribute
+ : boost::spirit::traits::attribute_of<Subject, Context, Iterator>
+ {};
+
+ simple_columns_generator(Subject const& s)
+ : subject(s)
+ {}
+
+ // This function is called during the actual output generation process.
+ // It dispatches to the embedded generator while supplying a new
+ // delimiter to use, wrapping the outer delimiter.
+ template <typename OutputIterator, typename Context
+ , typename Delimiter, typename Attribute>
+ bool generate(OutputIterator& sink, Context& ctx
+ , Delimiter const& delimiter, Attribute const& attr) const
+ {
+ columns_delimiter<Delimiter> d(delimiter);
+ return subject.generate(sink, ctx, d, attr) && d.final_delimit_out(sink);
+ }
+
+ // This function is called during error handling to create
+ // a human readable string for the error context.
+ template <typename Context>
+ boost::spirit::info what(Context& ctx) const
+ {
+ return boost::spirit::info("columns", subject.what(ctx));
+ }
+
+ Subject subject;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// instantiation of the generator
+namespace boost { namespace spirit { namespace karma
+{
+ // This is the factory function object invoked in order to create
+ // an instance of our simple_columns_generator.
+ template <typename Subject, typename Modifiers>
+ struct make_directive<custom_generator::tag::columns, Subject, Modifiers>
+ {
+ typedef custom_generator::simple_columns_generator<Subject> result_type;
+
+ result_type operator()(unused_type, Subject const& s, unused_type) const
+ {
+ return result_type(s);
+ }
+ };
+}}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/lex/Jamfile b/src/boost/libs/spirit/example/lex/Jamfile
new file mode 100644
index 00000000..79887762
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/Jamfile
@@ -0,0 +1,32 @@
+#==============================================================================
+# Copyright (c) 2001-2009 Joel de Guzman
+# Copyright (c) 2001-2009 Hartmut Kaiser
+#
+# Distributed under the 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
+ : requirements
+ <c++-template-depth>300
+ :
+ :
+ ;
+
+
+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 print_number_tokenids : print_number_tokenids.cpp ;
+exe word_count : word_count.cpp ;
+exe word_count_functor : word_count_functor.cpp ;
+exe word_count_lexer : word_count_lexer.cpp ;
+exe word_count_functor_flex : word_count_functor_flex.cpp ;
+exe strip_comments : strip_comments.cpp ;
+exe strip_comments_lexer : strip_comments_lexer.cpp ;
+exe custom_token_attribute : custom_token_attribute.cpp ;
+
+exe lexer_debug_support : lexer_debug_support.cpp ;
diff --git a/src/boost/libs/spirit/example/lex/custom_token_attribute.cpp b/src/boost/libs/spirit/example/lex/custom_token_attribute.cpp
new file mode 100644
index 00000000..e29bbcee
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/custom_token_attribute.cpp
@@ -0,0 +1,112 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to demonstrate how custom, user defined types
+// can be easily integrated with the lexer as token value types. Moreover, the
+// custom token values are properly exposed to the parser as well, allowing to
+// retrieve the custom values using the built in parser attribute propagation
+// rules.
+
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/qi.hpp>
+
+namespace lex = boost::spirit::lex;
+namespace qi = boost::spirit::qi;
+namespace mpl = boost::mpl;
+
+///////////////////////////////////////////////////////////////////////////////
+// This is just a simple custom rational data structure holding two ints to be
+// interpreted as a rational number
+struct rational
+{
+ rational(int n = 0, int d = 0)
+ : nominator_(n), denominator_(d)
+ {}
+
+ int nominator_;
+ int denominator_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// A rational is represented as "{n,d}", where 'n' and 'd' are the nominator
+// and denominator of the number. We use Spirit.Qi to do the low level parsing
+// of the input sequence as matched by the lexer. Certainly, any other
+// conversion could be used instead.
+//
+// The lexer uses the template assign_to_attribute_from_iterators<> to convert
+// the matched input sequence (pair of iterators) to the token value type as
+// specified while defining the lex::token_def<>.
+//
+// Our specialization of assign_to_attribute_from_iterators<> for the rational
+// data type defined above has to be placed into the
+// namespace boost::spirit::traits, otherwise it won't be found by the library.
+namespace boost { namespace spirit { namespace traits
+{
+ template <typename Iterator>
+ struct assign_to_attribute_from_iterators<rational, Iterator>
+ {
+ static void
+ call(Iterator const& first, Iterator const& last, rational& attr)
+ {
+ int x, y;
+ Iterator b = first;
+ qi::parse(b, last,
+ '{' >> qi::int_ >> ',' >> qi::int_ >> '}', x, y);
+ attr = rational(x, y);
+ }
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+// a lexer recognizing a single token type: rational
+template <typename Lexer>
+struct lex_rational : lex::lexer<Lexer>
+{
+ lex_rational()
+ {
+ this->self.add_pattern("INT", "[1-9][0-9]*");
+
+ rt = "\\{{INT},{INT}\\}";
+ this->self.add(rt);
+ }
+ lex::token_def<rational> rt;
+};
+
+
+int main()
+{
+ // the token type needs to know the iterator type of the underlying
+ // input and the set of used token value types
+ typedef lex::lexertl::token<std::string::iterator,
+ mpl::vector<rational> > token_type;
+
+ // use actor_lexer<> here if your token definitions have semantic
+ // actions
+ typedef lex::lexertl::lexer<token_type> lexer_type;
+
+ // this is the iterator exposed by the lexer, we use this for parsing
+ typedef lexer_type::iterator_type iterator_type;
+
+ // create a lexer instance
+ std::string input("{3,4}");
+ std::string::iterator s = input.begin();
+
+ lex_rational<lexer_type> lex;
+ iterator_type b = lex.begin(s, input.end());
+
+ // use the embedded token_def as a parser, it exposes its token value type
+ // as its parser attribute type
+ rational r;
+ if (!qi::parse(b, lex.end(), lex.rt, r))
+ {
+ std::cerr << "Parsing failed!" << std::endl;
+ return -1;
+ }
+
+ std::cout << "Parsing succeeded: {"
+ << r.nominator_ << ", " << r.denominator_ << "}" << std::endl;
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/lex/example.hpp b/src/boost/libs/spirit/example/lex/example.hpp
new file mode 100644
index 00000000..41399a5f
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example.hpp
@@ -0,0 +1,26 @@
+// Copyright (c) 2001-2010 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>());
+}
+
diff --git a/src/boost/libs/spirit/example/lex/example1.cpp b/src/boost/libs/spirit/example/lex/example1.cpp
new file mode 100644
index 00000000..b157b082
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example1.cpp
@@ -0,0 +1,133 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Simple lexer/parser to test the Spirit installation.
+//
+// This example shows, how to create a simple lexer recognizing 5 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.
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+// Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example1_tokens : lex::lexer<Lexer>
+{
+ example1_tokens()
+ {
+ // define tokens and associate them with the lexer
+ identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+ this->self = lex::char_(',') | '{' | '}' | identifier;
+
+ // any token definition to be used as the skip parser during parsing
+ // has to be associated with a separate lexer state (here 'WS')
+ this->white_space = "[ \\t\\n]+";
+ this->self("WS") = white_space;
+ }
+
+ lex::token_def<> identifier, white_space;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct example1_grammar
+ : qi::grammar<Iterator, qi::in_state_skipper<lex::token_def<> > >
+{
+ template <typename TokenDef>
+ example1_grammar(TokenDef const& tok)
+ : example1_grammar::base_type(start)
+ {
+ start = '{' >> *(tok.identifier >> -ascii::char_(',')) >> '}';
+ }
+
+ qi::rule<Iterator, qi::in_state_skipper<lex::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 lex::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 lex::lexertl::lexer<token_type> lexer_type;
+
+ // This is the lexer type (derived from the given lexer type).
+ typedef example1_tokens<lexer_type> example1_lex;
+
+ // This is the iterator type exposed by the lexer
+ typedef example1_lex::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_lex lex; // Our lexer
+ example1_grammar calc(lex); // Our grammar definition
+
+ 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 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 = qi::phrase_parse(iter, end, calc, qi::in_state("WS")[lex.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;
+}
diff --git a/src/boost/libs/spirit/example/lex/example1.input b/src/boost/libs/spirit/example/lex/example1.input
new file mode 100644
index 00000000..e2aa2b62
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example1.input
@@ -0,0 +1,5 @@
+{
+ hello world,
+ hello world,
+ goodbye
+}
diff --git a/src/boost/libs/spirit/example/lex/example2.cpp b/src/boost/libs/spirit/example/lex/example2.cpp
new file mode 100644
index 00000000..68a47667
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example2.cpp
@@ -0,0 +1,169 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_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::ascii;
+using boost::phoenix::ref;
+
+///////////////////////////////////////////////////////////////////////////////
+// Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example2_tokens : lex::lexer<Lexer>
+{
+ example2_tokens()
+ {
+ // 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. Note that
+ // single character token definitions as used below always get
+ // interpreted literally and never as special regex characters. This is
+ // done to be able to assign single characters the id of their character
+ // code value, allowing to reference those as literals in Qi grammars.
+ this->self = lex::token_def<>(',') | '!' | '.' | '?' | ' ' | '\n' | word;
+ }
+
+ lex::token_def<> word;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct example2_grammar : qi::grammar<Iterator>
+{
+ template <typename TokenDef>
+ example2_grammar(TokenDef const& tok)
+ : example2_grammar::base_type(story)
+ , 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);
+ }
+
+ qi::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 lex::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 lex::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 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 lexer
+ example2_grammar calc(tokens); // Our parser
+
+ 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 = tokens.begin(it, str.end());
+ iterator_type end = tokens.end();
+
+ // Parsing is done based on the token stream, not the character
+ // stream read from the input.
+ bool r = qi::parse(iter, end, calc);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "There were "
+ << calc.commands << " commands, "
+ << calc.questions << " questions, and "
+ << calc.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;
+}
diff --git a/src/boost/libs/spirit/example/lex/example2.input b/src/boost/libs/spirit/example/lex/example2.input
new file mode 100644
index 00000000..2f768330
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example2.input
@@ -0,0 +1,7 @@
+Our hiking boots are ready. So, let's pack!
+
+Have you the plane tickets for there and back?
+
+I do, I do. We're all ready to go. Grab my hand and be my beau.
+
+
diff --git a/src/boost/libs/spirit/example/lex/example3.cpp b/src/boost/libs/spirit/example/lex/example3.cpp
new file mode 100644
index 00000000..83800331
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example3.cpp
@@ -0,0 +1,150 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+// Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example3_tokens : lex::lexer<Lexer>
+{
+ example3_tokens()
+ {
+ // define the tokens to match
+ ellipses = "\\.\\.\\.";
+ number = "[0-9]+";
+
+ // associate the tokens and the token set with the lexer
+ this->self = ellipses | '(' | ')' | number;
+
+ // define the whitespace to ignore (spaces, tabs, newlines and C-style
+ // comments)
+ this->self("WS")
+ = lex::token_def<>("[ \\t\\n]+") // whitespace
+ | "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/" // C style comments
+ ;
+ }
+
+ // these tokens expose the iterator_range of the matched input sequence
+ lex::token_def<> ellipses, identifier, number;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example3_grammar
+ : qi::grammar<Iterator, qi::in_state_skipper<Lexer> >
+{
+ template <typename TokenDef>
+ example3_grammar(TokenDef const& tok)
+ : example3_grammar::base_type(start)
+ {
+ 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);
+ }
+
+ qi::rule<Iterator, qi::in_state_skipper<Lexer> > 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 lex::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 lex::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 example3_tokens::iterator_type iterator_type;
+
+ // this is the type of the grammar to parse
+ typedef example3_grammar<iterator_type, example3_tokens::lexer_def> 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 lexer
+ example3_grammar calc(tokens); // Our parser
+
+ 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 = tokens.begin(it, str.end());
+ iterator_type end = tokens.end();
+
+ // Parsing is done based on the token stream, not the character
+ // stream read from the input.
+ // Note how we use the lexer defined above as the skip parser.
+ bool r = qi::phrase_parse(iter, end, calc, qi::in_state("WS")[tokens.self]);
+
+ 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;
+}
diff --git a/src/boost/libs/spirit/example/lex/example3.input b/src/boost/libs/spirit/example/lex/example3.input
new file mode 100644
index 00000000..497cab43
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example3.input
@@ -0,0 +1,5 @@
+/* the following are couplets */
+(1) (1 2) (1 2 3) ...
+((1)) ((1 2)(3 4)) (((1) (2 3) (1 2 (3) 4))) ...
+(((1))) ...
+
diff --git a/src/boost/libs/spirit/example/lex/example4.cpp b/src/boost/libs/spirit/example/lex/example4.cpp
new file mode 100644
index 00000000..2970340a
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example4.cpp
@@ -0,0 +1,227 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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 attributes to tokens and how to access
+// the token attributes from inside the grammar.
+//
+// We use explicit token attribute types, making the corresponding token instances
+// carry convert the matched input into an instance of that type. The token
+// attribute 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using boost::phoenix::val;
+
+///////////////////////////////////////////////////////////////////////////////
+// Token definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example4_tokens : lex::lexer<Lexer>
+{
+ example4_tokens()
+ {
+ // define the tokens to match
+ identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+ constant = "[0-9]+";
+ if_ = "if";
+ else_ = "else";
+ while_ = "while";
+
+ // associate the tokens and the token set with the lexer
+ this->self = lex::token_def<>('(') | ')' | '{' | '}' | '=' | ';' | constant;
+ this->self += if_ | else_ | while_ | identifier;
+
+ // define the whitespace to ignore (spaces, tabs, newlines and C-style
+ // comments)
+ this->self("WS")
+ = lex::token_def<>("[ \\t\\n]+")
+ | "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
+ ;
+ }
+
+//[example4_token_def
+ // these tokens expose the iterator_range of the matched input sequence
+ lex::token_def<> if_, else_, while_;
+
+ // The following two tokens have an associated attribute type, 'identifier'
+ // carries a string (the identifier name) and 'constant' carries the
+ // matched integer value.
+ //
+ // Note: any token attribute type explicitly specified in 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 attributes 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 them being copied around.
+ lex::token_def<std::string> identifier;
+ lex::token_def<unsigned int> constant;
+//]
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example4_grammar
+ : qi::grammar<Iterator, qi::in_state_skipper<Lexer> >
+{
+ template <typename TokenDef>
+ example4_grammar(TokenDef const& tok)
+ : example4_grammar::base_type(program)
+ {
+ using boost::spirit::_val;
+
+ 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 boost::variant<unsigned int, std::string> expression_type;
+
+ qi::rule<Iterator, qi::in_state_skipper<Lexer> > program, block, statement;
+ qi::rule<Iterator, qi::in_state_skipper<Lexer> > assignment, if_stmt;
+ qi::rule<Iterator, qi::in_state_skipper<Lexer> > while_stmt;
+
+ // the expression is the only rule having a return value
+ qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> > 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 attribute 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 attribute will be generated from the matched input
+ // sequence every time it is requested. But as soon as you specify at
+ // least one token attribute type you'll have to list all attribute types
+ // used for token_def<> declarations in the token definition class above,
+ // otherwise compilation errors will occur.
+ typedef lex::lexertl::token<
+ base_iterator_type, boost::mpl::vector<unsigned int, std::string>
+ > token_type;
+//]
+ // Here we use the lexertl based lexer engine.
+ typedef lex::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 example4_tokens::iterator_type iterator_type;
+
+ // this is the type of the grammar to parse
+ typedef example4_grammar<iterator_type, example4_tokens::lexer_def> 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 lexer
+ example4_grammar calc(tokens); // Our parser
+
+ 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 = tokens.begin(it, str.end());
+ iterator_type end = tokens.end();
+
+ // Parsing is done based on the token stream, not the character
+ // stream read from the input.
+ // Note how we use the lexer 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 = qi::phrase_parse(iter, end, calc, qi::in_state("WS")[tokens.self]);
+
+ 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;
+}
diff --git a/src/boost/libs/spirit/example/lex/example4.input b/src/boost/libs/spirit/example/lex/example4.input
new file mode 100644
index 00000000..7a5ff76d
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example4.input
@@ -0,0 +1,17 @@
+/* example4.input */
+{
+
+ if (variable) { a = b ; }
+
+ while (10) {
+
+ if (2) { b = 10 ; }
+ if (x) { c = x ; } else { d = 10 ; }
+
+ }
+
+ variable = 42;
+
+}
+
+
diff --git a/src/boost/libs/spirit/example/lex/example5.cpp b/src/boost/libs/spirit/example/lex/example5.cpp
new file mode 100644
index 00000000..8083042c
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example5.cpp
@@ -0,0 +1,273 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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 attributes to tokens and how to access the
+// token attributes 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 'omit' 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+using boost::phoenix::val;
+
+///////////////////////////////////////////////////////////////////////////////
+// Token definition base, defines all tokens for the base grammar below
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct example5_base_tokens : lex::lexer<Lexer>
+{
+protected:
+ // this lexer is supposed to be used as a base type only
+ example5_base_tokens() {}
+
+public:
+ void init_token_definitions()
+ {
+ // define the tokens to match
+ identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+ constant = "[0-9]+";
+ if_ = "if";
+ while_ = "while";
+
+ // associate the tokens and the token set with the lexer
+ this->self += lex::token_def<>('(') | ')' | '{' | '}' | '=' | ';' | constant;
+ this->self += if_ | while_ | identifier;
+
+ // define the whitespace to ignore (spaces, tabs, newlines and C-style
+ // comments)
+ this->self("WS")
+ = lex::token_def<>("[ \\t\\n]+")
+ | "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
+ ;
+ }
+
+ // these tokens have no attribute
+ lex::token_def<lex::omit> if_, while_;
+
+ // The following two tokens have an associated attribute type, 'identifier'
+ // carries a string (the identifier name) and 'constant' carries the
+ // matched integer value.
+ //
+ // Note: any token attribute type explicitly specified in 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 attributes 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 them being copied around.
+ lex::token_def<std::string> identifier;
+ lex::token_def<unsigned int> constant;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition base, defines a basic language
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example5_base_grammar
+ : qi::grammar<Iterator, qi::in_state_skipper<Lexer> >
+{
+ template <typename TokenDef>
+ example5_base_grammar(TokenDef const& tok)
+ : example5_base_grammar::base_type(program)
+ {
+ using boost::spirit::_val;
+
+ 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 qi::in_state_skipper<Lexer> skipper_type;
+
+ qi::rule<Iterator, skipper_type> program, block, statement;
+ qi::rule<Iterator, skipper_type> assignment, if_stmt;
+ qi::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;
+ qi::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 example5_base_tokens<Lexer> base_type;
+
+ example5_tokens()
+ {
+ // 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
+ this->self = else_;
+
+ // now add the token definitions from the base class
+ this->base_type::init_token_definitions();
+ }
+
+ // this token has no attribute
+ lex::token_def<lex::omit> 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
+ // example5_base_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 attribute 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 attribute will be generated from the matched input
+ // sequence every time it is requested. But as soon as you specify at
+ // least one token attribute type you'll have to list all attribute types
+ // used for token_def<> declarations in the token definition class above,
+ // otherwise compilation errors will occur.
+ typedef lex::lexertl::token<
+ base_iterator_type, boost::mpl::vector<unsigned int, std::string>
+ > token_type;
+
+ // Here we use the lexertl based lexer engine.
+ typedef lex::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 example5_tokens::iterator_type iterator_type;
+
+ // this is the type of the grammar to parse
+ typedef example5_grammar<iterator_type, example5_tokens::lexer_def> 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 lexer
+ example5_grammar calc(tokens); // Our parser
+
+ 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 = tokens.begin(it, str.end());
+ iterator_type end = tokens.end();
+
+ // Parsing is done based on the token stream, not the character
+ // stream read from the input.
+ // Note how we use the lexer 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 = qi::phrase_parse(iter, end, calc, qi::in_state(ws)[tokens.self]);
+
+ 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;
+}
diff --git a/src/boost/libs/spirit/example/lex/example5.input b/src/boost/libs/spirit/example/lex/example5.input
new file mode 100644
index 00000000..1cbecf52
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example5.input
@@ -0,0 +1,16 @@
+/* example5.input */
+{
+
+ if (variable) { a = b ; }
+
+ while (10) {
+
+ if (2) { b = 10 ; }
+ if (x) { c = x ; } else { d = 10 ; }
+
+ }
+
+ variable = 42;
+ if (variable) { a = b ; } else { }
+}
+
diff --git a/src/boost/libs/spirit/example/lex/example6.cpp b/src/boost/libs/spirit/example/lex/example6.cpp
new file mode 100644
index 00000000..843b2d98
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example6.cpp
@@ -0,0 +1,249 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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 attributes to tokens and how to access the
+// token attributes 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+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 : lex::lexer<Lexer>
+{
+ example6_tokens()
+ {
+ // define the tokens to match
+ identifier = "[a-zA-Z_][a-zA-Z0-9_]*";
+ constant = "[0-9]+";
+
+ // associate the tokens and the token set with the lexer
+ this->self = lex::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.
+ this->self.add
+ (constant, ID_CONSTANT)
+ ("if", ID_IF)
+ ("else", ID_ELSE)
+ ("while", ID_WHILE)
+ (identifier, ID_IDENTIFIER)
+ ;
+
+ // define the whitespace to ignore (spaces, tabs, newlines and C-style
+ // comments) and add those to another lexer state (here: "WS")
+ this->self("WS")
+ = lex::token_def<>("[ \\t\\n]+")
+ | "\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/"
+ ;
+ }
+
+ // The following two tokens have an associated attribute type, identifier
+ // carries a string (the identifier name) and constant carries the matched
+ // integer value.
+ //
+ // Note: any token attribute type explicitly specified in 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 attributes 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 them being copied around.
+ lex::token_def<std::string> identifier;
+ lex::token_def<unsigned int> constant;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator, typename Lexer>
+struct example6_grammar
+ : qi::grammar<Iterator, qi::in_state_skipper<Lexer> >
+{
+ template <typename TokenDef>
+ example6_grammar(TokenDef const& tok)
+ : example6_grammar::base_type(program)
+ {
+ using boost::spirit::_val;
+
+ 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 boost::variant<unsigned int, std::string> expression_type;
+
+ qi::rule<Iterator, qi::in_state_skipper<Lexer> > program, block, statement;
+ qi::rule<Iterator, qi::in_state_skipper<Lexer> > assignment, if_stmt;
+ qi::rule<Iterator, qi::in_state_skipper<Lexer> > while_stmt;
+
+ // the expression is the only rule having a return value
+ qi::rule<Iterator, expression_type(), qi::in_state_skipper<Lexer> > 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 attribute 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 attribute will be generated from the matched input
+ // sequence every time it is requested. But as soon as you specify at
+ // least one token attribute type you'll have to list all attribute types
+ // used for token_def<> declarations in the token definition class above,
+ // otherwise compilation errors will occur.
+ typedef lex::lexertl::token<
+ base_iterator_type, boost::mpl::vector<unsigned int, std::string>
+ > token_type;
+
+ // Here we use the lexertl based lexer engine.
+ typedef lex::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 example6_tokens::iterator_type iterator_type;
+
+ // this is the type of the grammar to parse
+ typedef example6_grammar<iterator_type, example6_tokens::lexer_def> 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 lexer
+ example6_grammar calc(tokens); // Our parser
+
+ 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 = tokens.begin(it, str.end());
+ iterator_type end = tokens.end();
+
+ // Parsing is done based on the token stream, not the character
+ // stream read from the input.
+ // Note how we use the lexer 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 = qi::phrase_parse(iter, end, calc, qi::in_state(ws)[tokens.self]);
+
+ 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;
+}
diff --git a/src/boost/libs/spirit/example/lex/example6.input b/src/boost/libs/spirit/example/lex/example6.input
new file mode 100644
index 00000000..992cbeb3
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/example6.input
@@ -0,0 +1,17 @@
+/* example6.input */
+{
+
+ if (variable) { a = b ; }
+
+ while (10) {
+
+ if (2) { b = 10 ; }
+ if (x) { c = x ; } else { d = 10 ; }
+
+ }
+
+ variable = 42;
+
+}
+
+
diff --git a/src/boost/libs/spirit/example/lex/lexer_debug_support.cpp b/src/boost/libs/spirit/example/lex/lexer_debug_support.cpp
new file mode 100644
index 00000000..c6d3f76d
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/lexer_debug_support.cpp
@@ -0,0 +1,109 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG 1
+
+#include <boost/config/warning_disable.hpp>
+
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+
+namespace lex = boost::spirit::lex;
+namespace qi = boost::spirit::qi;
+namespace phoenix = boost::phoenix;
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct language_tokens : lex::lexer<Lexer>
+{
+ language_tokens()
+ {
+ tok_float = "float";
+ tok_int = "int";
+ floatlit = "[0-9]+\\.[0-9]*";
+ intlit = "[0-9]+";
+ ws = "[ \t\n]+";
+ identifier = "[a-zA-Z_][a-zA-Z_0-9]*";
+
+ this->self = ws [lex::_pass = lex::pass_flags::pass_ignore];
+ this->self += tok_float | tok_int | floatlit | intlit | identifier;
+ this->self += lex::char_('=');
+ }
+
+ lex::token_def<> tok_float, tok_int;
+ lex::token_def<> ws;
+ lex::token_def<double> floatlit;
+ lex::token_def<int> intlit;
+ lex::token_def<> identifier;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct language_grammar : qi::grammar<Iterator>
+{
+ template <typename Lexer>
+ language_grammar(language_tokens<Lexer> const& tok)
+ : language_grammar::base_type(declarations)
+ {
+ declarations = +number;
+ number =
+ tok.tok_float >> tok.identifier >> '=' >> tok.floatlit
+ | tok.tok_int >> tok.identifier >> '=' >> tok.intlit
+ ;
+
+ declarations.name("declarations");
+ number.name("number");
+ debug(declarations);
+ debug(number);
+ }
+
+ qi::rule<Iterator> declarations;
+ qi::rule<Iterator> number;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ // iterator type used to expose the underlying input stream
+ typedef std::string::iterator base_iterator_type;
+
+ // lexer type
+ typedef lex::lexertl::actor_lexer<
+ lex::lexertl::token<
+ base_iterator_type, boost::mpl::vector2<double, int>
+ > > lexer_type;
+
+ // iterator type exposed by the lexer
+ typedef language_tokens<lexer_type>::iterator_type iterator_type;
+
+ // now we use the types defined above to create the lexer and grammar
+ // object instances needed to invoke the parsing process
+ language_tokens<lexer_type> tokenizer; // Our lexer
+ language_grammar<iterator_type> g (tokenizer); // Our parser
+
+ // Parsing is done based on the token stream, not the character
+ // stream read from the input.
+ std::string str ("float f = 3.4\nint i = 6\n");
+ base_iterator_type first = str.begin();
+
+ bool r = lex::tokenize_and_parse(first, str.end(), tokenizer, g);
+
+ 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;
+}
diff --git a/src/boost/libs/spirit/example/lex/print_number_tokenids.cpp b/src/boost/libs/spirit/example/lex/print_number_tokenids.cpp
new file mode 100644
index 00000000..3789f0eb
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/print_number_tokenids.cpp
@@ -0,0 +1,121 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+// Token definition: We use the lexertl based lexer engine as the underlying
+// lexer type.
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct print_numbers_tokenids : lex::lexer<Lexer>
+{
+ // define tokens and associate it with the lexer, we set the lexer flags
+ // not to match newlines while matching a dot, so we need to add the
+ // '\n' explicitly below
+ print_numbers_tokenids()
+ : print_numbers_tokenids::base_type(lex::match_flags::match_not_dot_newline)
+ {
+ this->self = lex::token_def<int>("[0-9]+") | ".|\n";
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct print_numbers_grammar : qi::grammar<Iterator>
+{
+ print_numbers_grammar()
+ : print_numbers_grammar::base_type(start)
+ {
+ // we just know, that the token ids get assigned starting min_token_id
+ // so, "[0-9]+" gets the id 'min_token_id' and ".|\n" gets the id
+ // 'min_token_id+1'.
+
+ // this prints the token ids of the matched tokens
+ start = *( qi::tokenid(lex::min_token_id)
+ | qi::tokenid(lex::min_token_id+1)
+ )
+ [ std::cout << _1 << "\n" ]
+ ;
+ }
+
+ qi::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
+ // attribute and no lexer state is supported
+ typedef lex::lexertl::token<base_iterator_type, boost::mpl::vector<int>
+ , boost::mpl::false_> token_type;
+
+ // lexer type
+ typedef lex::lexertl::lexer<token_type> lexer_type;
+
+ // iterator type exposed by the lexer
+ typedef print_numbers_tokenids<lexer_type>::iterator_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_tokenids<lexer_type> print_tokens; // Our lexer
+ print_numbers_grammar<iterator_type> print; // Our parser
+
+ // Parsing is done based on 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 = lex::tokenize_and_parse(first, str.end(), print_tokens, print);
+
+ 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;
+}
+
+
+
diff --git a/src/boost/libs/spirit/example/lex/print_numbers.cpp b/src/boost/libs/spirit/example/lex/print_numbers.cpp
new file mode 100644
index 00000000..e128af97
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/print_numbers.cpp
@@ -0,0 +1,118 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+// Token definition: We use the lexertl based lexer engine as the underlying
+// lexer type.
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct print_numbers_tokens : lex::lexer<Lexer>
+{
+ // define tokens and associate it with the lexer, we set the lexer flags
+ // not to match newlines while matching a dot, so we need to add the
+ // '\n' explicitly below
+ print_numbers_tokens()
+ : print_numbers_tokens::base_type(lex::match_flags::match_not_dot_newline)
+ {
+ this->self = lex::token_def<int>("[0-9]+") | ".|\n";
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct print_numbers_grammar : qi::grammar<Iterator>
+{
+ print_numbers_grammar()
+ : print_numbers_grammar::base_type(start)
+ {
+ // we just know, that the token ids get assigned starting min_token_id
+ // so, "[0-9]+" gets the id 'min_token_id' and ".|\n" gets the id
+ // 'min_token_id+1'.
+ start = *( qi::token(lex::min_token_id) [ std::cout << _1 << "\n" ]
+ | qi::token(lex::min_token_id+1)
+ )
+ ;
+ }
+
+ qi::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
+ // attribute and no lexer state is supported
+ typedef lex::lexertl::token<base_iterator_type, boost::mpl::vector<int>
+ , boost::mpl::false_> token_type;
+
+ // lexer type
+ typedef lex::lexertl::lexer<token_type> lexer_type;
+
+ // iterator type exposed by the lexer
+ typedef print_numbers_tokens<lexer_type>::iterator_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 lexer
+ print_numbers_grammar<iterator_type> print; // Our parser
+
+ // Parsing is done based on 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 = lex::tokenize_and_parse(first, str.end(), print_tokens, print);
+
+ 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;
+}
+
+
+
diff --git a/src/boost/libs/spirit/example/lex/print_numbers.input b/src/boost/libs/spirit/example/lex/print_numbers.input
new file mode 100644
index 00000000..992cbeb3
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/print_numbers.input
@@ -0,0 +1,17 @@
+/* example6.input */
+{
+
+ if (variable) { a = b ; }
+
+ while (10) {
+
+ if (2) { b = 10 ; }
+ if (x) { c = x ; } else { d = 10 ; }
+
+ }
+
+ variable = 42;
+
+}
+
+
diff --git a/src/boost/libs/spirit/example/lex/reference.cpp b/src/boost/libs/spirit/example/lex/reference.cpp
new file mode 100644
index 00000000..0a878e24
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/reference.cpp
@@ -0,0 +1,30 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+//[reference_lex_includes
+#include <boost/spirit/include/lex.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <iostream>
+#include <string>
+//]
+
+//[reference_lex_test
+//]
+
+int main()
+{
+ {
+ //[reference_lex_using_declarations_char
+ //]
+
+ //[reference_lex_char
+ //]
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/Jamfile b/src/boost/libs/spirit/example/lex/static_lexer/Jamfile
new file mode 100644
index 00000000..25c30d0d
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/Jamfile
@@ -0,0 +1,15 @@
+#==============================================================================
+# Copyright (c) 2001-2009 Hartmut Kaiser
+#
+# Distributed under the 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 word_count_generate : word_count_generate.cpp ;
+exe word_count_static : word_count_static.cpp ;
+
+exe word_count_lexer_generate : word_count_lexer_generate.cpp ;
+exe word_count_lexer_static : word_count_lexer_static.cpp ;
+
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count.input b/src/boost/libs/spirit/example/lex/static_lexer/word_count.input
new file mode 100644
index 00000000..2f768330
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count.input
@@ -0,0 +1,7 @@
+Our hiking boots are ready. So, let's pack!
+
+Have you the plane tickets for there and back?
+
+I do, I do. We're all ready to go. Grab my hand and be my beau.
+
+
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count_generate.cpp b/src/boost/libs/spirit/example/lex/static_lexer/word_count_generate.cpp
new file mode 100644
index 00000000..87f0527f
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count_generate.cpp
@@ -0,0 +1,45 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show, how 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/config/warning_disable.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/lex_generate_static_lexertl.hpp>
+
+#include <fstream>
+
+#include "word_count_tokens.hpp"
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+//[wc_static_generate_main
+int main(int argc, char* argv[])
+{
+ // create the lexer object instance needed to invoke the generator
+ word_count_tokens<lex::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 suffix of the tables and functions to be generated
+ //
+ // The suffix "wc" used below results in a type lexertl::static_::lexer_wc
+ // to be generated, which needs to be passed as a template parameter to the
+ // lexertl::static_lexer template (see word_count_static.cpp).
+ return lex::lexertl::generate_static_dfa(word_count, out, "wc") ? 0 : -1;
+}
+//]
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_generate.cpp b/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_generate.cpp
new file mode 100644
index 00000000..65593cda
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_generate.cpp
@@ -0,0 +1,45 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show, how 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_lexer_static.cpp)
+
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/lex_generate_static_lexertl.hpp>
+
+#include <fstream>
+
+#include "word_count_lexer_tokens.hpp"
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+//[wcl_static_generate_main
+int main(int argc, char* argv[])
+{
+ // create the lexer object instance needed to invoke the generator
+ word_count_lexer_tokens<lex::lexertl::actor_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_lexer_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
+ //
+ // The suffix "wcl" used below results in a type lexertl::static_::lexer_wcl
+ // to be generated, which needs to be passed as a template parameter to the
+ // lexertl::static_lexer template (see word_count_lexer_static.cpp).
+ return lex::lexertl::generate_static_dfa(word_count, out, "wcl") ? 0 : -1;
+}
+//]
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_static.cpp b/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_static.cpp
new file mode 100644
index 00000000..2bda5adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_static.cpp
@@ -0,0 +1,84 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show, how 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_DEBUG
+// #define BOOST_SPIRIT_LEXERTL_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+
+#include <iostream>
+#include <string>
+
+#include "../example.hpp"
+#include "word_count_lexer_tokens.hpp" // token definition
+#include "word_count_lexer_static.hpp" // generated tokenizer
+
+using namespace boost::spirit;
+
+///////////////////////////////////////////////////////////////////////////////
+//[wcl_static_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 'omit' as the token attribute type generates a token class
+ // notholding any token attribute 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 lex::lexertl::token<char const*, lex::omit, boost::mpl::false_> 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.
+ //
+ // As we specified the suffix "wcl" while generating the static tables we
+ // need to pass the type lexertl::static_::lexer_wcl as the second template
+ // parameter below (see word_count_lexer_generate.cpp).
+ typedef lex::lexertl::static_actor_lexer<
+ token_type, lex::lexertl::static_::lexer_wcl
+ > lexer_type;
+
+ // create the lexer object instance needed to invoke the lexical analysis
+ word_count_lexer_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 = lex::tokenize(first, last, 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;
+}
+//]
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_static.hpp b/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_static.hpp
new file mode 100644
index 00000000..e69b936e
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_static.hpp
@@ -0,0 +1,164 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_WCL_NOV_10_2009_17_20_29)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_WCL_NOV_10_2009_17_20_29
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_wcl[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_wcl = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_wcl (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ enum {end_state_index, id_index, unique_id_index, state_index, bol_index,
+ eol_index, dead_state_index, dfa_offset};
+
+ static const std::size_t npos = static_cast<std::size_t>(~0);
+ static const std::size_t lookup_[256] = {
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 8, 7, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 8, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9 };
+ static const std::size_t dfa_alphabet_ = 10;
+ static const std::size_t dfa_[50] = {
+ 0, 0, 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, 0, 2, 1, 65537,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 65538, 2, 0, 0, 0, 0, 0,
+ 0, 0 };
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
+ Iterator curr_ = start_token_;
+ bool end_state_ = *ptr_ != 0;
+ std::size_t id_ = *(ptr_ + id_index);
+ std::size_t uid_ = *(ptr_ + unique_id_index);
+ Iterator end_token_ = start_token_;
+
+ while (curr_ != end_)
+ {
+ std::size_t const state_ =
+ ptr_[lookup_[static_cast<unsigned char>(*curr_++)]];
+
+ if (state_ == 0) break;
+
+ ptr_ = &dfa_[state_ * dfa_alphabet_];
+
+ if (*ptr_)
+ {
+ end_state_ = true;
+ id_ = *(ptr_ + id_index);
+ uid_ = *(ptr_ + unique_id_index);
+ end_token_ = curr_;
+ }
+ }
+
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_wcl
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_wcl;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_wcl[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_wcl(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_tokens.hpp b/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_tokens.hpp
new file mode 100644
index 00000000..af52a209
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count_lexer_tokens.hpp
@@ -0,0 +1,62 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(SPIRIT_LEXER_EXAMPLE_WORD_COUNT_LEXER_TOKENS_FEB_10_2008_0739PM)
+#define SPIRIT_LEXER_EXAMPLE_WORD_COUNT_LEXER_TOKENS_FEB_10_2008_0739PM
+
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_statement.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+///////////////////////////////////////////////////////////////////////////////
+struct distance_func
+{
+ template <typename Iterator1, typename Iterator2>
+ struct result : boost::iterator_difference<Iterator1> {};
+
+ template <typename Iterator1, typename Iterator2>
+ typename result<Iterator1, Iterator2>::type
+ operator()(Iterator1& begin, Iterator2& end) const
+ {
+ return std::distance(begin, end);
+ }
+};
+boost::phoenix::function<distance_func> const distance = distance_func();
+
+//[wcl_static_token_definition
+template <typename Lexer>
+struct word_count_lexer_tokens : boost::spirit::lex::lexer<Lexer>
+{
+ word_count_lexer_tokens()
+ : c(0), w(0), l(0)
+ , word("[^ \t\n]+") // define tokens
+ , eol("\n")
+ , any(".")
+ {
+ using boost::spirit::lex::_start;
+ using boost::spirit::lex::_end;
+ using boost::phoenix::ref;
+
+ // associate tokens with the lexer
+ this->self
+ = word [++ref(w), ref(c) += distance(_start, _end)]
+ | eol [++ref(c), ++ref(l)]
+ | any [++ref(c)]
+ ;
+ }
+
+ std::size_t c, w, l;
+ boost::spirit::lex::token_def<> word, eol, any;
+};
+//]
+
+#endif
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count_static.cpp b/src/boost/libs/spirit/example/lex/static_lexer/word_count_static.cpp
new file mode 100644
index 00000000..4ba3bb53
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count_static.cpp
@@ -0,0 +1,120 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show, how 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+//[wc_static_include
+#include <boost/spirit/include/lex_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::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// 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 : qi::grammar<Iterator>
+{
+ template <typename TokenDef>
+ word_count_grammar(TokenDef const& tok)
+ : word_count_grammar::base_type(start)
+ , c(0), w(0), l(0)
+ {
+ 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) ]
+ | lit('\n') [ ++ref(l), ++ref(c) ]
+ | qi::token(IDANY) [ ++ref(c) ]
+ )
+ ;
+ }
+
+ std::size_t c, w, l; // counter for characters, words, and lines
+ qi::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 lex::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.
+ //
+ // As we specified the suffix "wc" while generating the static tables we
+ // need to pass the type lexertl::static_::lexer_wc as the second template
+ // parameter below (see word_count_generate.cpp).
+ typedef lex::lexertl::static_lexer<
+ token_type, lex::lexertl::static_::lexer_wc
+ > lexer_type;
+
+ // Define the iterator type exposed by the lexer.
+ typedef word_count_tokens<lexer_type>::iterator_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 lexer
+ word_count_grammar<iterator_type> g (word_count); // Our parser
+
+ // 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 token stream, not the character stream.
+ bool r = lex::tokenize_and_parse(first, last, word_count, g);
+
+ if (r) { // success
+ std::cout << "lines: " << g.l << ", words: " << g.w
+ << ", characters: " << g.c << "\n";
+ }
+ else {
+ std::string rest(first, last);
+ std::cerr << "Parsing failed\n" << "stopped at: \""
+ << rest << "\"\n";
+ }
+ return 0;
+}
+//]
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count_static.hpp b/src/boost/libs/spirit/example/lex/static_lexer/word_count_static.hpp
new file mode 100644
index 00000000..4a7aa3c6
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count_static.hpp
@@ -0,0 +1,164 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_WC_NOV_10_2009_17_20_04)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_WC_NOV_10_2009_17_20_04
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_wc[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_wc = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_wc (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ enum {end_state_index, id_index, unique_id_index, state_index, bol_index,
+ eol_index, dead_state_index, dfa_offset};
+
+ static 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, 9, 7, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 9, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 8, 8, 8, 8, 8, 8,
+ 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_ = 10;
+ static const std::size_t dfa_[50] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 2, 4, 1, 65536, 0, 0,
+ 0, 0, 0, 0, 2, 0, 1, 10,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 1, 65537, 2, 0, 0, 0, 0, 0,
+ 0, 0 };
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
+ Iterator curr_ = start_token_;
+ bool end_state_ = *ptr_ != 0;
+ std::size_t id_ = *(ptr_ + id_index);
+ std::size_t uid_ = *(ptr_ + unique_id_index);
+ Iterator end_token_ = start_token_;
+
+ while (curr_ != end_)
+ {
+ std::size_t const state_ =
+ ptr_[lookup_[static_cast<unsigned char>(*curr_++)]];
+
+ if (state_ == 0) break;
+
+ ptr_ = &dfa_[state_ * dfa_alphabet_];
+
+ if (*ptr_)
+ {
+ end_state_ = true;
+ id_ = *(ptr_ + id_index);
+ uid_ = *(ptr_ + unique_id_index);
+ end_token_ = curr_;
+ }
+ }
+
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_wc
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_wc;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_wc[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_wc(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/lex/static_lexer/word_count_tokens.hpp b/src/boost/libs/spirit/example/lex/static_lexer/word_count_tokens.hpp
new file mode 100644
index 00000000..5828adde
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/static_lexer/word_count_tokens.hpp
@@ -0,0 +1,41 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(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<BaseLexer>
+{
+ word_count_tokens()
+ : word_count_tokens::base_type(
+ boost::spirit::lex::match_flags::match_not_dot_newline)
+ {
+ // define tokens and associate them with the lexer
+ word = "[^ \t\n]+";
+ this->self = word | '\n' | boost::spirit::lex::token_def<>(".", IDANY);
+ }
+
+ boost::spirit::lex::token_def<std::string> word;
+};
+//]
+
+#endif
diff --git a/src/boost/libs/spirit/example/lex/strip_comments.cpp b/src/boost/libs/spirit/example/lex/strip_comments.cpp
new file mode 100644
index 00000000..c4e0913a
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/strip_comments.cpp
@@ -0,0 +1,163 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_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;
+
+///////////////////////////////////////////////////////////////////////////////
+// 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 : lex::lexer<Lexer>
+{
+ strip_comments_tokens()
+ : strip_comments_tokens::base_type(lex::match_flags::match_default)
+ {
+ // define tokens and associate them with the lexer
+ cppcomment = "\"//\"[^\n]*"; // '//[^\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.
+ this->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.
+ this->self("COMMENT").add
+ (endcomment)
+ (".", IDANY)
+ ;
+ }
+
+ lex::token_def<> cppcomment, ccomment, endcomment;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct strip_comments_grammar : qi::grammar<Iterator>
+{
+ template <typename TokenDef>
+ strip_comments_grammar(TokenDef const& tok)
+ : strip_comments_grammar::base_type(start)
+ {
+ // The in_state("COMMENT")[...] parser component switches the lexer
+ // state to be 'COMMENT' during the matching of the embedded parser.
+ start = *( tok.ccomment
+ >> qi::in_state("COMMENT")
+ [
+ // the lexer is in the 'COMMENT' state during
+ // matching of the following parser components
+ *token(IDANY) >> tok.endcomment
+ ]
+ | tok.cppcomment
+ | qi::token(IDANY) [ std::cout << _1 ]
+ )
+ ;
+ }
+
+ qi::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
+ lex::lexertl::lexer<lex::lexertl::token<base_iterator_type> >
+ lexer_type;
+
+ // iterator type exposed by the lexer
+ typedef strip_comments_tokens<lexer_type>::iterator_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 lexer
+ strip_comments_grammar<iterator_type> g (strip_comments); // Our parser
+
+ // Parsing is done based on 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 = lex::tokenize_and_parse(first, str.end(), strip_comments, g);
+
+ 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;
+}
+
+
+
diff --git a/src/boost/libs/spirit/example/lex/strip_comments.input b/src/boost/libs/spirit/example/lex/strip_comments.input
new file mode 100644
index 00000000..bed0f071
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/strip_comments.input
@@ -0,0 +1,162 @@
+// Copyright (c) 2001-2009 Hartmut Kaiser
+//
+// Distributed under the 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/config/warning_disable.hpp>
+#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;
+
+///////////////////////////////////////////////////////////////////////////////
+// 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<Lexer>
+{
+ strip_comments_tokens()
+ {
+ // 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.
+ this->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.
+ this->self("COMMENT").add
+ (endcomment)
+ (".", IDANY)
+ ;
+ }
+
+ token_def<> cppcomment, ccomment, endcomment;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+template <typename Iterator>
+struct strip_comments_grammar : grammar<Iterator>
+{
+ template <typename TokenDef>
+ strip_comments_grammar(TokenDef const& tok)
+ : strip_comments_grammar::base_type(start)
+ {
+ // 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) [ std::cout << _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;
+
+ // lexer type
+ typedef lexertl::lexer<lexertl::token<base_iterator_type> > lexer_type;
+
+ // iterator type exposed by the lexer
+ typedef strip_comments_tokens<lexer_type>::iterator_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 lexer
+ strip_comments_grammar<iterator_type> g (strip_comments); // Our grammar
+
+ // Parsing is done based on 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(), strip_comments, g);
+
+ 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;
+}
+
+
+
diff --git a/src/boost/libs/spirit/example/lex/strip_comments_lexer.cpp b/src/boost/libs/spirit/example/lex/strip_comments_lexer.cpp
new file mode 100644
index 00000000..30e0b34b
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/strip_comments_lexer.cpp
@@ -0,0 +1,172 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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/config/warning_disable.hpp>
+#include <boost/spirit/include/lex_lexertl.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;
+
+///////////////////////////////////////////////////////////////////////////////
+// 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
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Simple custom semantic action function object used to print the matched
+// input sequence for a particular token
+template <typename Char, typename Traits>
+struct echo_input_functor
+{
+ echo_input_functor (std::basic_ostream<Char, Traits>& os_)
+ : os(os_) {}
+
+ // This is called by the semantic action handling code during the lexing
+ template <typename Iterator, typename Context>
+ void operator()(Iterator const& b, Iterator const& e
+ , BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&
+ , std::size_t&, Context&) const
+ {
+ os << std::string(b, e);
+ }
+
+ std::basic_ostream<Char, Traits>& os;
+};
+
+template <typename Char, typename Traits>
+inline echo_input_functor<Char, Traits>
+echo_input(std::basic_ostream<Char, Traits>& os)
+{
+ return echo_input_functor<Char, Traits>(os);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Another simple custom semantic action function object used to switch the
+// state of the lexer
+struct set_lexer_state
+{
+ set_lexer_state(char const* state_)
+ : state(state_) {}
+
+ // This is called by the semantic action handling code during the lexing
+ template <typename Iterator, typename Context>
+ void operator()(Iterator const&, Iterator const&
+ , BOOST_SCOPED_ENUM(boost::spirit::lex::pass_flags)&
+ , std::size_t&, Context& ctx) const
+ {
+ ctx.set_state_name(state.c_str());
+ }
+
+ std::string state;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+template <typename Lexer>
+struct strip_comments_tokens : lex::lexer<Lexer>
+{
+ strip_comments_tokens()
+ : strip_comments_tokens::base_type(lex::match_flags::match_default)
+ {
+ // define tokens and associate them with the lexer
+ cppcomment = "\"//\"[^\n]*"; // '//[^\n]*'
+ ccomment = "\"/*\""; // '/*'
+ endcomment = "\"*/\""; // '*/'
+ any = std::string(".");
+ eol = "\n";
+
+ // The following tokens are associated with the default lexer state
+ // (the "INITIAL" state). Specifying 'INITIAL' as a lexer state is
+ // strictly optional.
+ this->self
+ = cppcomment
+ | ccomment [ set_lexer_state("COMMENT") ]
+ | eol [ echo_input(std::cout) ]
+ | any [ echo_input(std::cout) ]
+ ;
+
+ // The following tokens are associated with the lexer state 'COMMENT'.
+ this->self("COMMENT")
+ = endcomment [ set_lexer_state("INITIAL") ]
+ | "\n"
+ | std::string(".")
+ ;
+ }
+
+ lex::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
+ lex::lexertl::actor_lexer<lex::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 lexer
+
+ // No parsing is done alltogether, everything happens in the lexer semantic
+ // actions.
+ std::string str (read_from_file(1 == argc ? "strip_comments.input" : argv[1]));
+ base_iterator_type first = str.begin();
+ bool r = lex::tokenize(first, str.end(), strip_comments);
+
+ if (!r) {
+ std::string rest(first, str.end());
+ std::cerr << "Lexical analysis failed\n" << "stopped at: \""
+ << rest << "\"\n";
+ }
+ return 0;
+}
+
+
+
diff --git a/src/boost/libs/spirit/example/lex/word_count.cpp b/src/boost/libs/spirit/example/lex/word_count.cpp
new file mode 100644
index 00000000..c6b21d95
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/word_count.cpp
@@ -0,0 +1,166 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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
+
+#include <boost/config/warning_disable.hpp>
+//[wcp_includes
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/lex_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::ascii;
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+// 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 : lex::lexer<Lexer>
+{
+ word_count_tokens()
+ {
+ // define patterns (lexer macros) to be used during token definition
+ // below
+ this->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
+ this->self.add
+ (word) // no token id is needed here
+ ('\n') // characters are usable as tokens as well
+ (".", IDANY) // string literals will not be escaped by the library
+ ;
+ }
+
+ // the token 'word' exposes the matched string as its parser attribute
+ lex::token_def<std::string> word;
+};
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+// Grammar definition
+///////////////////////////////////////////////////////////////////////////////
+//[wcp_grammar_definition
+template <typename Iterator>
+struct word_count_grammar : qi::grammar<Iterator>
+{
+ template <typename TokenDef>
+ word_count_grammar(TokenDef const& tok)
+ : word_count_grammar::base_type(start)
+ , c(0), w(0), l(0)
+ {
+ using boost::phoenix::ref;
+ using boost::phoenix::size;
+
+ start = *( tok.word [++ref(w), ref(c) += size(_1)]
+ | lit('\n') [++ref(c), ++ref(l)]
+ | qi::token(IDANY) [++ref(c)]
+ )
+ ;
+ }
+
+ std::size_t c, w, l;
+ qi::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 attribute
+>*/ typedef lex::lexertl::token<
+ char const*, boost::mpl::vector<std::string>
+ > token_type;
+
+/*< Define the lexer type to use implementing the state machine
+>*/ typedef lex::lexertl::lexer<token_type> lexer_type;
+
+/*< Define the iterator type exposed by the lexer type
+>*/ typedef word_count_tokens<lexer_type>::iterator_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 lexer
+ word_count_grammar<iterator_type> g (word_count); // Our parser
+
+ // 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 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 token stream.
+>*/ bool r = lex::tokenize_and_parse(first, last, word_count, g);
+
+ if (r) {
+ std::cout << "lines: " << g.l << ", words: " << g.w
+ << ", characters: " << g.c << "\n";
+ }
+ else {
+ std::string rest(first, last);
+ std::cerr << "Parsing failed\n" << "stopped at: \""
+ << rest << "\"\n";
+ }
+ return 0;
+}
+//]
diff --git a/src/boost/libs/spirit/example/lex/word_count.input b/src/boost/libs/spirit/example/lex/word_count.input
new file mode 100644
index 00000000..2f768330
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/word_count.input
@@ -0,0 +1,7 @@
+Our hiking boots are ready. So, let's pack!
+
+Have you the plane tickets for there and back?
+
+I do, I do. We're all ready to go. Grab my hand and be my beau.
+
+
diff --git a/src/boost/libs/spirit/example/lex/word_count_functor.cpp b/src/boost/libs/spirit/example/lex/word_count_functor.cpp
new file mode 100644
index 00000000..f1969aac
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/word_count_functor.cpp
@@ -0,0 +1,183 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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
+
+#include <boost/config/warning_disable.hpp>
+//[wcf_includes
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/bind.hpp>
+#include <boost/ref.hpp>
+//]
+
+#include <iostream>
+#include <string>
+
+#include "example.hpp"
+
+//[wcf_namespaces
+namespace lex = 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 `lex::lexer<>`, where the corresponding template parameter (here:
+ `lex::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 : lex::lexer<Lexer>
+{
+ word_count_tokens()
+ {
+ // define tokens (the regular expression to match and the corresponding
+ // token id) and add them to the lexer
+ this->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 specific to boost::bind 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
+ // attribute 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 function
+ object. 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<lex::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, 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;
+}
+//]
+
diff --git a/src/boost/libs/spirit/example/lex/word_count_functor.flex b/src/boost/libs/spirit/example/lex/word_count_functor.flex
new file mode 100644
index 00000000..d9c00503
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/word_count_functor.flex
@@ -0,0 +1,59 @@
+%{
+// Copyright (c) 2001-2009 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/timer.hpp>
+#if defined(_WIN32)
+ #include <io.h>
+#endif
+ #define ID_WORD 1000
+ #define ID_EOL 1001
+ #define ID_CHAR 1002
+%}
+
+%%
+[^ \t\n]+ { return ID_WORD; }
+\n { return ID_EOL; }
+. { return ID_CHAR; }
+%%
+
+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;
+}
+
+int 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);
+ fclose(yyin);
+ return 0;
+}
+
+extern "C" int yywrap()
+{
+ return 1;
+}
+
diff --git a/src/boost/libs/spirit/example/lex/word_count_functor_flex.cpp b/src/boost/libs/spirit/example/lex/word_count_functor_flex.cpp
new file mode 100644
index 00000000..5fc9e734
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/word_count_functor_flex.cpp
@@ -0,0 +1,1576 @@
+#line 2 "c:\\CVS\\boost\\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\\boost\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+#define INITIAL 0
+#line 2 "c:\\CVS\\boost\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/timer.hpp>
+#if defined(_WIN32)
+ #include <io.h>
+#endif
+ #define ID_WORD 1000
+ #define ID_EOL 1001
+ #define ID_CHAR 1002
+#line 380 "c:\\CVS\\boost\\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 16 "c:\\CVS\\boost\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+
+#line 544 "c:\\CVS\\boost\\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 17 "c:\\CVS\\boost\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+{ return ID_WORD; }
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 18 "c:\\CVS\\boost\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+{ return ID_EOL; }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 19 "c:\\CVS\\boost\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+{ return ID_CHAR; }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 20 "c:\\CVS\\boost\\libs\\spirit\\example\\lex\\word_count_functor.flex"
+ECHO;
+ YY_BREAK
+#line 647 "c:\\CVS\\boost\\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 20 "c:\\CVS\\boost\\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;
+}
+
+int 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);
+ fclose(yyin);
+ return 0;
+}
+
+extern "C" int yywrap()
+{
+ return 1;
+}
+
diff --git a/src/boost/libs/spirit/example/lex/word_count_lexer.cpp b/src/boost/libs/spirit/example/lex/word_count_lexer.cpp
new file mode 100644
index 00000000..57225e40
--- /dev/null
+++ b/src/boost/libs/spirit/example/lex/word_count_lexer.cpp
@@ -0,0 +1,152 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example 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
+
+#include <boost/config/warning_disable.hpp>
+//[wcl_includes
+#include <boost/spirit/include/lex_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
+namespace lex = 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.
+///////////////////////////////////////////////////////////////////////////////
+struct distance_func
+{
+ template <typename Iterator1, typename Iterator2>
+ struct result : boost::iterator_difference<Iterator1> {};
+
+ template <typename Iterator1, typename Iterator2>
+ typename result<Iterator1, Iterator2>::type
+ operator()(Iterator1 const& begin, Iterator2 const& end) const
+ {
+ return std::distance(begin, end);
+ }
+};
+boost::phoenix::function<distance_func> const distance = distance_func();
+
+//[wcl_token_definition
+template <typename Lexer>
+struct word_count_tokens : lex::lexer<Lexer>
+{
+ word_count_tokens()
+ : c(0), w(0), l(0)
+ , word("[^ \t\n]+") // define tokens
+ , eol("\n")
+ , any(".")
+ {
+ using boost::spirit::lex::_start;
+ using boost::spirit::lex::_end;
+ using boost::phoenix::ref;
+
+ // associate tokens with the lexer
+ this->self
+ = word [++ref(w), ref(c) += distance(_start, _end)]
+ | eol [++ref(c), ++ref(l)]
+ | any [++ref(c)]
+ ;
+ }
+
+ std::size_t c, w, l;
+ lex::token_def<> word, eol, any;
+};
+//]
+
+///////////////////////////////////////////////////////////////////////////////
+//[wcl_main
+int main(int argc, char* argv[])
+{
+
+/*< Specifying `omit` as the token attribute type generates a token class
+ not holding any token attribute at all (not even the iterator range of the
+ matched input sequence), therefore 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
+ lex::lexertl::token<char const*, lex::omit, boost::mpl::false_>
+ token_type;
+
+/*< This defines the lexer type to use
+>*/ typedef lex::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;
+
+/*< Read input from the given file, tokenize all the input, while discarding
+ all generated tokens
+>*/ 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()];
+
+/*< Create a pair of iterators returning the sequence of generated tokens
+>*/ lexer_type::iterator_type iter = word_count_lexer.begin(first, last);
+ lexer_type::iterator_type end = word_count_lexer.end();
+
+/*< Here we simply iterate over all tokens, making sure to break the loop
+ if an invalid token gets returned from the lexer
+>*/ while (iter != end && token_is_valid(*iter))
+ ++iter;
+
+ if (iter == end) {
+ 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;
+}
+//]
diff --git a/src/boost/libs/spirit/example/qi/Jamfile b/src/boost/libs/spirit/example/qi/Jamfile
new file mode 100644
index 00000000..a071c0d2
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/Jamfile
@@ -0,0 +1,48 @@
+#==============================================================================
+# Copyright (c) 2001-2007 Joel de Guzman
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+project spirit-qi-example
+ : requirements
+ <c++-template-depth>300
+ :
+ :
+ ;
+
+exe actions_ : actions.cpp ;
+exe sum : sum.cpp ;
+exe complex_number : complex_number.cpp ;
+exe employee : employee.cpp ;
+exe roman : roman.cpp ;
+exe reference : reference.cpp ;
+exe mini_xml1 : mini_xml1.cpp ;
+exe mini_xml2 : mini_xml2.cpp ;
+exe mini_xml3 : mini_xml3.cpp ;
+exe num_list1 : num_list1.cpp ;
+exe num_list2 : num_list2.cpp ;
+exe num_list3 : num_list3.cpp ;
+exe num_list4 : num_list4.cpp ;
+exe reorder_struct : reorder_struct.cpp ;
+exe parse_date : parse_date.cpp ;
+exe expect : expect.cpp ;
+
+exe key_value_sequence : key_value_sequence.cpp ;
+exe key_value_sequence_ordered : key_value_sequence_ordered.cpp ;
+exe key_value_sequence_empty_value : key_value_sequence_empty_value.cpp ;
+
+exe iter_pos_parser : iter_pos_parser.cpp ;
+exe boost_array : boost_array.cpp ;
+exe display_attribute_type : display_attribute_type.cpp ;
+exe adapt_template_struct : adapt_template_struct.cpp ;
+
+exe unescaped_string : unescaped_string.cpp ;
+
+exe calc_utree_naive : calc_utree_naive.cpp ;
+exe calc_utree_ast : calc_utree_ast.cpp ;
+exe calc_utree : calc_utree.cpp ;
+
+exe nabialek : nabialek.cpp ;
+exe typeof : typeof.cpp ;
+
diff --git a/src/boost/libs/spirit/example/qi/actions.cpp b/src/boost/libs/spirit/example/qi/actions.cpp
new file mode 100644
index 00000000..c5379703
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/actions.cpp
@@ -0,0 +1,108 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/bind.hpp>
+
+#include <iostream>
+
+// Presented are various ways to attach semantic actions
+// * Using plain function pointer
+// * Using simple function object
+// * Using boost.bind with a plain function
+// * Using boost.bind with a member function
+// * Using boost.lambda
+
+//[tutorial_semantic_action_functions
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ // A plain function
+ void print(int const& i)
+ {
+ std::cout << i << std::endl;
+ }
+
+ // A member function
+ struct writer
+ {
+ void print(int const& i) const
+ {
+ std::cout << i << std::endl;
+ }
+ };
+
+ // A function object
+ struct print_action
+ {
+ void operator()(int const& i, qi::unused_type, qi::unused_type) const
+ {
+ std::cout << i << std::endl;
+ }
+ };
+}
+//]
+
+int main()
+{
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::parse;
+ using client::print;
+ using client::writer;
+ using client::print_action;
+
+ { // example using plain function
+
+ char const *first = "{42}", *last = first + std::strlen(first);
+ //[tutorial_attach_actions1
+ parse(first, last, '{' >> int_[&print] >> '}');
+ //]
+ }
+
+ { // example using simple function object
+
+ char const *first = "{43}", *last = first + std::strlen(first);
+ //[tutorial_attach_actions2
+ parse(first, last, '{' >> int_[print_action()] >> '}');
+ //]
+ }
+
+ { // example using boost.bind with a plain function
+
+ char const *first = "{44}", *last = first + std::strlen(first);
+ //[tutorial_attach_actions3
+ parse(first, last, '{' >> int_[boost::bind(&print, _1)] >> '}');
+ //]
+ }
+
+ { // example using boost.bind with a member function
+
+ char const *first = "{44}", *last = first + std::strlen(first);
+ //[tutorial_attach_actions4
+ writer w;
+ parse(first, last, '{' >> int_[boost::bind(&writer::print, &w, _1)] >> '}');
+ //]
+ }
+
+ { // example using boost.lambda
+
+ namespace lambda = boost::lambda;
+ char const *first = "{45}", *last = first + std::strlen(first);
+ using lambda::_1;
+ //[tutorial_attach_actions5
+ parse(first, last, '{' >> int_[std::cout << _1 << '\n'] >> '}');
+ //]
+ }
+
+ return 0;
+}
+
+
+
+
diff --git a/src/boost/libs/spirit/example/qi/adapt_template_struct.cpp b/src/boost/libs/spirit/example/qi/adapt_template_struct.cpp
new file mode 100644
index 00000000..360707d1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/adapt_template_struct.cpp
@@ -0,0 +1,92 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example demonstrates a trick allowing to adapt a template data
+// structure as a Fusion sequence in order to use is for direct attribute
+// propagation. For more information see
+// http://boost-spirit.com/home/2010/02/08/how-to-adapt-templates-as-a-fusion-sequence
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace qi = boost::spirit::qi;
+namespace fusion = boost::fusion;
+
+namespace client
+{
+ template <typename A, typename B>
+ struct data
+ {
+ A a;
+ B b;
+ };
+
+ template <typename Iterator, typename A, typename B>
+ struct data_grammar : qi::grammar<Iterator, data<A, B>()>
+ {
+ data_grammar() : data_grammar::base_type(start)
+ {
+ start = real_start;
+ real_start = qi::auto_ >> ',' >> qi::auto_;
+ }
+
+ qi::rule<Iterator, data<A, B>()> start;
+ qi::rule<Iterator, fusion::vector<A&, B&>()> real_start;
+ };
+}
+
+namespace boost { namespace spirit { namespace traits
+{
+ template <typename A, typename B>
+ struct transform_attribute<client::data<A, B>, fusion::vector<A&, B&>, qi::domain>
+ {
+ typedef fusion::vector<A&, B&> type;
+
+ static type pre(client::data<A, B>& val) { return type(val.a, val.b); }
+ static void post(client::data<A, B>&, fusion::vector<A&, B&> const&) {}
+ static void fail(client::data<A, B>&) {}
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA parser for Spirit utilizing an adapted template ...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me two comma separated integers:\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ client::data_grammar<std::string::const_iterator, long, int> g; // Our grammar
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::data<long, int> d;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, g, qi::space, d);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << d.a << "," << d.b << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/boost_array.cpp b/src/boost/libs/spirit/example/qi/boost_array.cpp
new file mode 100644
index 00000000..66485b97
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/boost_array.cpp
@@ -0,0 +1,119 @@
+// Copyright (c) 2009 Erik Bryan
+// Copyright (c) 2007-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <string>
+#include <vector>
+
+#include <boost/array.hpp>
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace qi = boost::spirit::qi;
+namespace ascii = boost::spirit::ascii;
+
+///////////////////////////////////////////////////////////////////////////////
+// create a wrapper holding the boost::array and a current insertion point
+namespace client
+{
+ namespace detail
+ {
+ template <typename T>
+ struct adapt_array;
+
+ template <typename T, std::size_t N>
+ struct adapt_array<boost::array<T, N> >
+ {
+ typedef boost::array<T, N> array_type;
+
+ adapt_array(array_type& arr)
+ : arr_(arr), current_(0) {}
+
+ // expose a push_back function compatible with std containers
+ bool push_back(typename array_type::value_type const& val)
+ {
+ // if the array is full, we need to bail out
+ // returning false will fail the parse
+ if (current_ >= N)
+ return false;
+
+ arr_[current_++] = val;
+ return true;
+ }
+
+ array_type& arr_;
+ std::size_t current_;
+ };
+ }
+
+ namespace result_of
+ {
+ template <typename T>
+ struct adapt_array;
+
+ template <typename T, std::size_t N>
+ struct adapt_array<boost::array<T, N> >
+ {
+ typedef detail::adapt_array<boost::array<T, N> > type;
+ };
+ }
+
+ template <typename T, std::size_t N>
+ inline detail::adapt_array<boost::array<T, N> >
+ adapt_array(boost::array<T, N>& arr)
+ {
+ return detail::adapt_array<boost::array<T, N> >(arr);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// specialize Spirit's container specific customization points for our adaptor
+namespace boost { namespace spirit { namespace traits
+{
+ template <typename T, std::size_t N>
+ struct is_container<client::detail::adapt_array<boost::array<T, N> > >
+ : boost::mpl::true_
+ {};
+
+ template <typename T, std::size_t N>
+ struct container_value<client::detail::adapt_array<boost::array<T, N> > >
+ {
+ typedef T type; // value type of container
+ };
+
+ template <typename T, std::size_t N>
+ struct push_back_container<
+ client::detail::adapt_array<boost::array<T, N> >, T>
+ {
+ static bool call(client::detail::adapt_array<boost::array<T, N> >& c
+ , T const& val)
+ {
+ return c.push_back(val);
+ }
+ };
+}}}
+
+int main()
+{
+ typedef std::string::const_iterator iterator_type;
+ typedef boost::array<int, 2> array_type;
+ typedef client::result_of::adapt_array<array_type>::type adapted_type;
+
+ array_type arr;
+
+ std::string str = "1 2";
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+
+ qi::rule<iterator_type, adapted_type(), ascii::space_type> r = *qi::int_;
+
+ adapted_type attr = client::adapt_array(arr);
+ bool result = qi::phrase_parse(iter, end, r, ascii::space, attr);
+
+ if (result)
+ std::cout << "Parsed: " << arr[0] << ", " << arr[1] << std::endl;
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/calc_utree.cpp b/src/boost/libs/spirit/example/qi/calc_utree.cpp
new file mode 100644
index 00000000..00293df3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/calc_utree.cpp
@@ -0,0 +1,166 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Plain calculator example demonstrating the grammar. The parser is a
+// syntax checker only and does not do any semantic evaluation.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ HK November 30, 2010 ] spirit2/utree
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// #define BOOST_SPIRIT_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+#include <iostream>
+#include <string>
+
+#if BOOST_PHOENIX_VERSION == 0x2000
+namespace boost { namespace phoenix
+{
+ // There's a bug in the Phoenix V2 type deduction mechanism that prevents
+ // correct return type deduction for the math operations below. Newer
+ // versions of Phoenix will be switching to BOOST_TYPEOF. In the meantime,
+ // we will use the specializations helping with return type deduction
+ // below:
+ template <>
+ struct result_of_plus<spirit::utree&, spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+
+ template <>
+ struct result_of_minus<spirit::utree&, spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+
+ template <>
+ struct result_of_multiplies<spirit::utree&, spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+
+ template <>
+ struct result_of_divides<spirit::utree&, spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+
+ template <>
+ struct result_of_negate<spirit::utree&>
+ {
+ typedef spirit::utree type;
+ };
+}}
+#endif
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace spirit = boost::spirit;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ using qi::uint_;
+ using qi::_val;
+ using qi::_1;
+
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [_val = _val + _1])
+ | ('-' >> term [_val = _val - _1])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [_val = _val * _1])
+ | ('/' >> factor [_val = _val / _1])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [_val = -_1])
+ | ('+' >> factor [_val = _1])
+ ;
+
+ BOOST_SPIRIT_DEBUG_NODE(expression);
+ BOOST_SPIRIT_DEBUG_NODE(term);
+ BOOST_SPIRIT_DEBUG_NODE(factor);
+ }
+
+ qi::rule<Iterator, ascii::space_type, spirit::utree()> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ using boost::spirit::ascii::space;
+ using boost::spirit::utree;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ utree ut;
+ bool r = phrase_parse(iter, end, calc, space, ut);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded: " << ut << "\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/calc_utree_ast.cpp b/src/boost/libs/spirit/example/qi/calc_utree_ast.cpp
new file mode 100644
index 00000000..3465ba08
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/calc_utree_ast.cpp
@@ -0,0 +1,164 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Plain calculator example demonstrating the grammar. The parser is a
+// syntax checker only and does not do any semantic evaluation.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ HK November 30, 2010 ] spirit2/utree
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// #define BOOST_SPIRIT_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace spirit = boost::spirit;
+
+ struct expr
+ {
+ template <typename T1, typename T2 = void>
+ struct result { typedef void type; };
+
+ expr(char op) : op(op) {}
+
+ void operator()(spirit::utree& expr, spirit::utree const& rhs) const
+ {
+ spirit::utree lhs;
+ lhs.swap(expr);
+ expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
+ expr.push_back(lhs);
+ expr.push_back(rhs);
+ }
+
+ char const op;
+ };
+ boost::phoenix::function<expr> const plus = expr('+');
+ boost::phoenix::function<expr> const minus = expr('-');
+ boost::phoenix::function<expr> const times = expr('*');
+ boost::phoenix::function<expr> const divide = expr('/');
+
+ struct negate_expr
+ {
+ template <typename T1, typename T2 = void>
+ struct result { typedef void type; };
+
+ void operator()(spirit::utree& expr, spirit::utree const& rhs) const
+ {
+ char const op = '-';
+ expr.clear();
+ expr.push_back(spirit::utf8_symbol_range_type(&op, &op+1));
+ expr.push_back(rhs);
+ }
+ };
+ boost::phoenix::function<negate_expr> neg;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ using qi::uint_;
+ using qi::_val;
+ using qi::_1;
+
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [plus(_val, _1)])
+ | ('-' >> term [minus(_val, _1)])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [times(_val, _1)])
+ | ('/' >> factor [divide(_val, _1)])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [neg(_val, _1)])
+ | ('+' >> factor [_val = _1])
+ ;
+
+ BOOST_SPIRIT_DEBUG_NODE(expression);
+ BOOST_SPIRIT_DEBUG_NODE(term);
+ BOOST_SPIRIT_DEBUG_NODE(factor);
+ }
+
+ qi::rule<Iterator, ascii::space_type, spirit::utree()> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ using boost::spirit::ascii::space;
+ using boost::spirit::utree;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ utree ut;
+ bool r = phrase_parse(iter, end, calc, space, ut);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded: " << ut << "\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/calc_utree_naive.cpp b/src/boost/libs/spirit/example/qi/calc_utree_naive.cpp
new file mode 100644
index 00000000..c6ac3ddb
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/calc_utree_naive.cpp
@@ -0,0 +1,134 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Plain calculator example demonstrating the grammar. The parser is a
+// syntax checker only and does not do any semantic evaluation.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ HK November 30, 2010 ] spirit2/utree
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// This rather naive example demonstrates that you can pass an instance of a
+// utree as the attribute for almost any grammar. As the result the utree will
+// be filled with the parse tree as generated during the parsing. This is most
+// of the time not what's desired, but is usually a good first step in order to
+// prepare your grammar to generate a customized AST. See the calc_utree_ast
+// example for a modified version of this grammar filling the attribute with a
+// AST (abstract syntax tree) representing the math expression as matched from
+// the input.
+
+// #define BOOST_SPIRIT_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/support_utree.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace spirit = boost::spirit;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type, spirit::utree()>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ using qi::uint_;
+ using qi::char_;
+
+ expression =
+ term
+ >> *( (char_('+') >> term)
+ | (char_('-') >> term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( (char_('*') >> factor)
+ | (char_('/') >> factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' >> expression >> ')'
+ | (char_('-') >> factor)
+ | (char_('+') >> factor)
+ ;
+
+ BOOST_SPIRIT_DEBUG_NODE(expression);
+ BOOST_SPIRIT_DEBUG_NODE(term);
+ BOOST_SPIRIT_DEBUG_NODE(factor);
+ }
+
+ qi::rule<Iterator, ascii::space_type, spirit::utree()> expression;
+ qi::rule<Iterator, ascii::space_type, spirit::utree::list_type()> term;
+ qi::rule<Iterator, ascii::space_type, spirit::utree::list_type()> factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ using boost::spirit::ascii::space;
+ using boost::spirit::utree;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ utree ut;
+ bool r = phrase_parse(iter, end, calc, space, ut);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded: " << ut << "\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/Jamfile b/src/boost/libs/spirit/example/qi/compiler_tutorial/Jamfile
new file mode 100644
index 00000000..bda2fad4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/Jamfile
@@ -0,0 +1,132 @@
+#==============================================================================
+# Copyright (c) 2001-2011 Joel de Guzman
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#==============================================================================
+project spirit-qi-compiler_tutorial
+ : requirements
+ <c++-template-depth>300
+ :
+ ;
+
+import modules ;
+
+exe calc1 : calc1.cpp ;
+exe calc2 : calc2.cpp ;
+exe calc3 : calc3.cpp ;
+exe calc4 : calc4.cpp ;
+exe calc5 : calc5.cpp ;
+exe calc6 : calc6.cpp ;
+
+exe calc7 :
+ calc7/vm.cpp
+ calc7/compiler.cpp
+ calc7/expression.cpp
+ calc7/statement.cpp
+ calc7/main.cpp
+;
+
+exe calc8 :
+ calc8/vm.cpp
+ calc8/compiler.cpp
+ calc8/expression.cpp
+ calc8/statement.cpp
+ calc8/main.cpp
+;
+
+exe mini_c :
+ mini_c/vm.cpp
+ mini_c/compiler.cpp
+ mini_c/expression.cpp
+ mini_c/statement.cpp
+ mini_c/function.cpp
+ mini_c/main.cpp
+;
+
+exe conjure1 :
+ conjure1/vm.cpp
+ conjure1/compiler.cpp
+ conjure1/expression.cpp
+ conjure1/statement.cpp
+ conjure1/function.cpp
+ conjure1/main.cpp
+;
+
+exe conjure2 :
+ conjure2/compiler.cpp
+ conjure2/expression.cpp
+ conjure2/function.cpp
+ conjure2/lexer.cpp
+ conjure2/main.cpp
+ conjure2/statement.cpp
+ conjure2/vm.cpp
+;
+
+#==============================================================================
+# conjure3 and above require LLVM. Make sure you provide the
+# LLVM_PATH in your bjam invocation. E.g.:
+#
+# bjam -sLLVM_PATH=C:/dev/llvm conjure3
+#
+#==============================================================================
+
+if [ modules.peek : LLVM_PATH ]
+{
+ LLVM_PATH = [ modules.peek : LLVM_PATH ] ;
+}
+
+if $(LLVM_PATH)
+{
+ path-constant LLVM_LIB_DEBUG_PATH : $(LLVM_PATH)/lib/Debug ;
+ path-constant LLVM_LIB_RELEASE_PATH : $(LLVM_PATH)/lib/Release ;
+
+ llvm_linker_flags =
+ "advapi32.lib"
+ "shell32.lib"
+ ;
+
+ llvm_debug_libs = [ glob $(LLVM_LIB_DEBUG_PATH)/LLVM*.lib ] ;
+ llvm_release_libs = [ glob $(LLVM_LIB_RELEASE_PATH)/LLVM*.lib ] ;
+
+ rule build_exe_1 ( target-name : sources + : requirements * )
+ {
+ local llvm_lib ;
+ if <variant>debug in $(requirements)
+ {
+ llvm_lib = $(llvm_debug_libs) ;
+ }
+ else
+ {
+ llvm_lib = $(llvm_release_libs) ;
+ }
+
+ exe $(target-name)
+ : $(sources)
+ $(llvm_lib)
+ : $(requirements)
+ <toolset>msvc
+ <include>$(LLVM_PATH)/include
+ <linkflags>$(llvm_linker_flags)
+ ;
+ }
+
+ rule build_exe ( target-name : sources + )
+ {
+ build_exe_1 $(target-name) : $(sources) : <variant>debug ;
+ build_exe_1 $(target-name) : $(sources) : <variant>release ;
+ }
+
+ build_exe conjure3 :
+ conjure3/compiler.cpp
+ conjure3/expression.cpp
+ conjure3/function.cpp
+ conjure3/lexer.cpp
+ conjure3/main.cpp
+ conjure3/statement.cpp
+ conjure3/vm.cpp
+ ;
+}
+
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc1.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc1.cpp
new file mode 100644
index 00000000..d070172f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc1.cpp
@@ -0,0 +1,118 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Plain calculator example demonstrating the grammar. The parser is a
+// syntax checker only and does not do any semantic evaluation.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ JDG February 21, 2011 ] spirit2.5
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::uint_type uint_;
+
+ expression =
+ term
+ >> *( ('+' >> term)
+ | ('-' >> term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( ('*' >> factor)
+ | ('/' >> factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' >> expression >> ')'
+ | ('-' >> factor)
+ | ('+' >> factor)
+ ;
+ }
+
+ qi::rule<Iterator, ascii::space_type> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ boost::spirit::ascii::space_type space; // Our skipper
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, calc, space);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \" " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp
new file mode 100644
index 00000000..92e03f49
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc2.cpp
@@ -0,0 +1,131 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating the grammar and semantic actions
+// using plain functions. The parser prints code suitable for a stack
+// based virtual machine.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 4, 2007 ] spirit2
+// [ JDG February 21, 2011 ] spirit2.5
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Semantic actions
+ ////////////////////////////////////////////////////////1///////////////////////
+ namespace
+ {
+ void do_int(int n) { std::cout << "push " << n << std::endl; }
+ void do_add() { std::cout << "add\n"; }
+ void do_subt() { std::cout << "subtract\n"; }
+ void do_mult() { std::cout << "mult\n"; }
+ void do_div() { std::cout << "divide\n"; }
+ void do_neg() { std::cout << "negate\n"; }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::uint_type uint_;
+
+ expression =
+ term
+ >> *( ('+' >> term [&do_add])
+ | ('-' >> term [&do_subt])
+ )
+ ;
+
+ term =
+ factor
+ >> *( ('*' >> factor [&do_mult])
+ | ('/' >> factor [&do_div])
+ )
+ ;
+
+ factor =
+ uint_ [&do_int]
+ | '(' >> expression >> ')'
+ | ('-' >> factor [&do_neg])
+ | ('+' >> factor)
+ ;
+ }
+
+ qi::rule<Iterator, ascii::space_type> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ boost::spirit::ascii::space_type space; // Our skipper
+ calculator calc; // Our grammar
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, calc, space);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \" " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc3.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc3.cpp
new file mode 100644
index 00000000..4f214e30
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc3.cpp
@@ -0,0 +1,124 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A calculator example demonstrating the grammar and semantic actions
+// using phoenix to do the actual expression evaluation. The parser is
+// essentially an "interpreter" that evaluates expressions on the fly.
+//
+// [ JDG June 29, 2002 ] spirit1
+// [ JDG March 5, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, int(), ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::_val_type _val;
+ qi::_1_type _1;
+ qi::uint_type uint_;
+
+ expression =
+ term [_val = _1]
+ >> *( ('+' >> term [_val += _1])
+ | ('-' >> term [_val -= _1])
+ )
+ ;
+
+ term =
+ factor [_val = _1]
+ >> *( ('*' >> factor [_val *= _1])
+ | ('/' >> factor [_val /= _1])
+ )
+ ;
+
+ factor =
+ uint_ [_val = _1]
+ | '(' >> expression [_val = _1] >> ')'
+ | ('-' >> factor [_val = -_1])
+ | ('+' >> factor [_val = _1])
+ ;
+ }
+
+ qi::rule<Iterator, int(), ascii::space_type> expression, term, factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+
+ boost::spirit::ascii::space_type space; // Our skipper
+ calculator calc; // Our grammar
+
+ std::string str;
+ int result;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, calc, space, result);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "result = " << result << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \" " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc4.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc4.cpp
new file mode 100644
index 00000000..645926f7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc4.cpp
@@ -0,0 +1,285 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST. The AST,
+// once created, is traversed, 1) To print its contents and
+// 2) To evaluate the result.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct program;
+
+ typedef boost::variant<
+ nil
+ , unsigned int
+ , boost::recursive_wrapper<signed_>
+ , boost::recursive_wrapper<program>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct program
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::signed_,
+ (char, sign)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (char, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::program,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST Printer
+ ///////////////////////////////////////////////////////////////////////////
+ struct printer
+ {
+ typedef void result_type;
+
+ void operator()(nil) const {}
+ void operator()(unsigned int n) const { std::cout << n; }
+
+ void operator()(operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': std::cout << " add"; break;
+ case '-': std::cout << " subt"; break;
+ case '*': std::cout << " mult"; break;
+ case '/': std::cout << " div"; break;
+ }
+ }
+
+ void operator()(signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': std::cout << " neg"; break;
+ case '+': std::cout << " pos"; break;
+ }
+ }
+
+ void operator()(program const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(operation const& oper, x.rest)
+ {
+ std::cout << ' ';
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST evaluator
+ ///////////////////////////////////////////////////////////////////////////
+ struct eval
+ {
+ typedef int result_type;
+
+ int operator()(nil) const { BOOST_ASSERT(0); return 0; }
+ int operator()(unsigned int n) const { return n; }
+
+ int operator()(operation const& x, int lhs) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': return lhs + rhs;
+ case '-': return lhs - rhs;
+ case '*': return lhs * rhs;
+ case '/': return lhs / rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(signed_ const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': return -rhs;
+ case '+': return +rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(program const& x) const
+ {
+ int state = boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(operation const& oper, x.rest)
+ {
+ state = (*this)(oper, state);
+ }
+ return state;
+ }
+ };
+}}
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ast::program(), ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::uint_type uint_;
+ qi::char_type char_;
+
+ expression =
+ term
+ >> *( (char_('+') >> term)
+ | (char_('-') >> term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( (char_('*') >> factor)
+ | (char_('/') >> factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' >> expression >> ')'
+ | (char_('-') >> factor)
+ | (char_('+') >> factor)
+ ;
+ }
+
+ qi::rule<Iterator, ast::program(), ascii::space_type> expression;
+ qi::rule<Iterator, ast::program(), ascii::space_type> term;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+ typedef client::ast::program ast_program;
+ typedef client::ast::printer ast_print;
+ typedef client::ast::eval ast_eval;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ calculator calc; // Our grammar
+ ast_program program; // Our program (AST)
+ ast_print print; // Prints the program
+ ast_eval eval; // Evaluates the program
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ boost::spirit::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, program);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ print(program);
+ std::cout << "\nResult: " << eval(program) << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \" " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc5.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc5.cpp
new file mode 100644
index 00000000..8aa71342
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc5.cpp
@@ -0,0 +1,339 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Same as Calc4, this time, we'll incorporate debugging support,
+// plus error handling and reporting.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Define this to enable debugging
+#define BOOST_SPIRIT_QI_DEBUG
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+//#define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct program;
+
+ typedef boost::variant<
+ nil
+ , unsigned int
+ , boost::recursive_wrapper<signed_>
+ , boost::recursive_wrapper<program>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct program
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ // print function for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::signed_,
+ (char, sign)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (char, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::program,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST Printer
+ ///////////////////////////////////////////////////////////////////////////
+ struct printer
+ {
+ typedef void result_type;
+
+ void operator()(nil) const {}
+ void operator()(unsigned int n) const { std::cout << n; }
+
+ void operator()(operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': std::cout << " add"; break;
+ case '-': std::cout << " subt"; break;
+ case '*': std::cout << " mult"; break;
+ case '/': std::cout << " div"; break;
+ }
+ }
+
+ void operator()(signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': std::cout << " neg"; break;
+ case '+': std::cout << " pos"; break;
+ }
+ }
+
+ void operator()(program const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(operation const& oper, x.rest)
+ {
+ std::cout << ' ';
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST evaluator
+ ///////////////////////////////////////////////////////////////////////////
+ struct eval
+ {
+ typedef int result_type;
+
+ int operator()(nil) const { BOOST_ASSERT(0); return 0; }
+ int operator()(unsigned int n) const { return n; }
+
+ int operator()(operation const& x, int lhs) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': return lhs + rhs;
+ case '-': return lhs - rhs;
+ case '*': return lhs * rhs;
+ case '/': return lhs / rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(signed_ const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': return -rhs;
+ case '+': return +rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(program const& x) const
+ {
+ int state = boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(operation const& oper, x.rest)
+ {
+ state = (*this)(oper, state);
+ }
+ return state;
+ }
+ };
+}}
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ using boost::phoenix::function;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ struct error_handler_
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ template <typename Iterator>
+ void operator()(
+ qi::info const& what
+ , Iterator err_pos, Iterator last) const
+ {
+ std::cout
+ << "Error! Expecting "
+ << what // what failed?
+ << " here: \""
+ << std::string(err_pos, last) // iterators to error-pos, end
+ << "\""
+ << std::endl
+ ;
+ }
+ };
+
+ function<error_handler_> const error_handler = error_handler_();
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ast::program(), ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ using qi::on_error;
+ using qi::fail;
+
+ expression =
+ term
+ >> *( (char_('+') > term)
+ | (char_('-') > term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( (char_('*') > factor)
+ | (char_('/') > factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' > expression > ')'
+ | (char_('-') > factor)
+ | (char_('+') > factor)
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODE(expression);
+ BOOST_SPIRIT_DEBUG_NODE(term);
+ BOOST_SPIRIT_DEBUG_NODE(factor);
+
+ // Error handling
+ on_error<fail>(expression, error_handler(_4, _3, _2));
+ }
+
+ qi::rule<Iterator, ast::program(), ascii::space_type> expression;
+ qi::rule<Iterator, ast::program(), ascii::space_type> term;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+ typedef client::ast::program ast_program;
+ typedef client::ast::printer ast_print;
+ typedef client::ast::eval ast_eval;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ calculator calc; // Our grammar
+ ast_program program; // Our program (AST)
+ ast_print print; // Prints the program
+ ast_eval eval; // Evaluates the program
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ boost::spirit::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, program);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ print(program);
+ std::cout << "\nResult: " << eval(program) << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc6.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc6.cpp
new file mode 100644
index 00000000..af362f3d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc6.cpp
@@ -0,0 +1,373 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Yet another calculator example! This time, we will compile to a simple
+// virtual machine. This is actually one of the very first Spirit example
+// circa 2000. Now, it's ported to Spirit2.
+//
+// [ JDG Sometime 2000 ] pre-boost
+// [ JDG September 18, 2002 ] spirit1
+// [ JDG April 8, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Define this to enable debugging
+//#define BOOST_SPIRIT_QI_DEBUG
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+//#define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct expression;
+
+ typedef boost::variant<
+ nil
+ , unsigned int
+ , boost::recursive_wrapper<signed_>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ // print function for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::signed_,
+ (char, sign)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (char, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+ op_int, // push constant integer into the stack
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ int top() const { return stack_ptr[-1]; };
+ void execute(std::vector<int> const& code);
+
+ private:
+
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+ };
+
+ void vmachine::execute(std::vector<int> const& code)
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+ stack_ptr = stack.begin();
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef void result_type;
+
+ std::vector<int>& code;
+ compiler(std::vector<int>& code)
+ : code(code) {}
+
+ void operator()(ast::nil) const { BOOST_ASSERT(0); }
+ void operator()(unsigned int n) const
+ {
+ code.push_back(op_int);
+ code.push_back(n);
+ }
+
+ void operator()(ast::operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': code.push_back(op_add); break;
+ case '-': code.push_back(op_sub); break;
+ case '*': code.push_back(op_mul); break;
+ case '/': code.push_back(op_div); break;
+ default: BOOST_ASSERT(0); break;
+ }
+ }
+
+ void operator()(ast::signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': code.push_back(op_neg); break;
+ case '+': break;
+ default: BOOST_ASSERT(0); break;
+ }
+ }
+
+ void operator()(ast::expression const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ BOOST_FOREACH(ast::operation const& oper, x.rest)
+ {
+ (*this)(oper);
+ }
+ }
+ };
+
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ using boost::phoenix::function;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ struct error_handler_
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ template <typename Iterator>
+ void operator()(
+ qi::info const& what
+ , Iterator err_pos, Iterator last) const
+ {
+ std::cout
+ << "Error! Expecting "
+ << what // what failed?
+ << " here: \""
+ << std::string(err_pos, last) // iterators to error-pos, end
+ << "\""
+ << std::endl
+ ;
+ }
+ };
+
+ function<error_handler_> const error_handler = error_handler_();
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct calculator : qi::grammar<Iterator, ast::expression(), ascii::space_type>
+ {
+ calculator() : calculator::base_type(expression)
+ {
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ using qi::on_error;
+ using qi::fail;
+
+ expression =
+ term
+ >> *( (char_('+') > term)
+ | (char_('-') > term)
+ )
+ ;
+
+ term =
+ factor
+ >> *( (char_('*') > factor)
+ | (char_('/') > factor)
+ )
+ ;
+
+ factor =
+ uint_
+ | '(' > expression > ')'
+ | (char_('-') > factor)
+ | (char_('+') > factor)
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expression)(term)(factor));
+
+ // Error handling
+ on_error<fail>(expression, error_handler(_4, _3, _2));
+ }
+
+ qi::rule<Iterator, ast::expression(), ascii::space_type> expression;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> term;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> factor;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::calculator<iterator_type> calculator;
+ typedef client::ast::expression ast_expression;
+ typedef client::compiler compiler;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::vmachine mach; // Our virtual machine
+ std::vector<int> code; // Our VM code
+ calculator calc; // Our grammar
+ ast_expression expression; // Our program (AST)
+ compiler compile(code); // Compiles the program
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ boost::spirit::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, expression);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ compile(expression);
+ mach.execute(code);
+ std::cout << "\nResult: " << mach.top() << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp
new file mode 100644
index 00000000..37365283
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/annotation.hpp
@@ -0,0 +1,78 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CALC7_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ this->dispatch(x, boost::is_base_of<ast::tagged, T>());
+ }
+
+ // This will catch all nodes except those inheriting from ast::tagged
+ template <typename T>
+ void dispatch(T& x, boost::mpl::false_) const
+ {
+ // (no-op) no need for tags
+ }
+
+ // This will catch all nodes inheriting from ast::tagged
+ template <typename T>
+ void dispatch(T& x, boost::mpl::true_) const
+ {
+ x.id = id;
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp
new file mode 100644
index 00000000..82fba496
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/ast.hpp
@@ -0,0 +1,117 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_AST_HPP)
+#define BOOST_SPIRIT_CALC7_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct signed_;
+ struct expression;
+
+ struct variable : tagged
+ {
+ variable(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , unsigned int
+ , variable
+ , boost::recursive_wrapper<signed_>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ variable lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ assignment assign;
+ };
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment>
+ statement;
+
+ typedef std::list<statement> statement_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+ inline std::ostream& operator<<(std::ostream& out, variable const& var) { out << var.name; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::signed_,
+ (char, sign)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (char, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::assignment, assign)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::variable, lhs)
+ (client::ast::expression, rhs)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp
new file mode 100644
index 00000000..8aa23017
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.cpp
@@ -0,0 +1,222 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+
+namespace client { namespace code_gen
+{
+ void program::op(int a)
+ {
+ code.push_back(a);
+ }
+
+ void program::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ }
+
+ void program::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ }
+
+ int const* program::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void program::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void program::print_variables(std::vector<int> const& stack) const
+ {
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
+ }
+ }
+
+ void program::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << "local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ std::cout << "op_neg" << std::endl;
+ break;
+
+ case op_add:
+ std::cout << "op_add" << std::endl;
+ break;
+
+ case op_sub:
+ std::cout << "op_sub" << std::endl;
+ break;
+
+ case op_mul:
+ std::cout << "op_mul" << std::endl;
+ break;
+
+ case op_div:
+ std::cout << "op_div" << std::endl;
+ break;
+
+ case op_load:
+ std::cout << "op_load " << locals[*pc++] << std::endl;
+ break;
+
+ case op_store:
+ std::cout << "op_store " << locals[*pc++] << std::endl;
+ break;
+
+ case op_int:
+ std::cout << "op_int " << *pc++ << std::endl;
+ break;
+
+ case op_stk_adj:
+ std::cout << "op_stk_adj " << *pc++ << std::endl;
+ break;
+ }
+ }
+ }
+
+ bool compiler::operator()(unsigned int x) const
+ {
+ program.op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable const& x) const
+ {
+ int const* p = program.find_var(x.name);
+ if (p == 0)
+ {
+ std::cout << x.id << std::endl;
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ program.op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::operation const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case '+': program.op(op_add); break;
+ case '-': program.op(op_sub); break;
+ case '*': program.op(op_mul); break;
+ case '/': program.op(op_div); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::signed_ const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.sign)
+ {
+ case '-': program.op(op_neg); break;
+ case '+': break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ BOOST_FOREACH(ast::operation const& oper, x.rest)
+ {
+ if (!(*this)(oper))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x) const
+ {
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = program.find_var(x.lhs.name);
+ if (p == 0)
+ {
+ std::cout << x.lhs.id << std::endl;
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ program.op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x) const
+ {
+ int const* p = program.find_var(x.assign.lhs.name);
+ if (p != 0)
+ {
+ std::cout << x.assign.lhs.id << std::endl;
+ error_handler(x.assign.lhs.id, "Duplicate variable: " + x.assign.lhs.name);
+ return false;
+ }
+ bool r = (*this)(x.assign.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ program.add_var(x.assign.lhs.name);
+ program.op(op_store, *program.find_var(x.assign.lhs.name));
+ }
+ return r;
+ }
+
+ bool compiler::operator()(ast::statement_list const& x) const
+ {
+ program.clear();
+
+ // op_stk_adj 0 for now. we'll know how many variables we'll have later
+ program.op(op_stk_adj, 0);
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!boost::apply_visitor(*this, s))
+ {
+ program.clear();
+ return false;
+ }
+ }
+ program[1] = program.nvars(); // now store the actual number of variables
+ return true;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp
new file mode 100644
index 00000000..179a315a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/compiler.hpp
@@ -0,0 +1,85 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_COMPILER_HPP)
+#define BOOST_SPIRIT_CALC7_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Program
+ ///////////////////////////////////////////////////////////////////////////
+ struct program
+ {
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[i]; }
+ int const& operator[](std::size_t i) const { return code[i]; }
+ void clear() { code.clear(); variables.clear(); }
+ std::vector<int> const& operator()() const { return code; }
+
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+
+ void print_variables(std::vector<int> const& stack) const;
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::vector<int> code;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(client::code_gen::program& program, ErrorHandler& error_handler_)
+ : program(program)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) const { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x) const;
+ bool operator()(ast::variable const& x) const;
+ bool operator()(ast::operation const& x) const;
+ bool operator()(ast::signed_ const& x) const;
+ bool operator()(ast::expression const& x) const;
+ bool operator()(ast::assignment const& x) const;
+ bool operator()(ast::variable_declaration const& x) const;
+ bool operator()(ast::statement_list const& x) const;
+
+ client::code_gen::program& program;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp
new file mode 100644
index 00000000..867e9ee7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/error_handler.hpp
@@ -0,0 +1,93 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CALC7_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ if (err_pos != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.cpp
new file mode 100644
index 00000000..32f44adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::expression<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp
new file mode 100644
index 00000000..916e26e7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression.hpp
@@ -0,0 +1,53 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CALC7_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct expression : qi::grammar<Iterator, ast::expression(), ascii::space_type>
+ {
+ expression(error_handler<Iterator>& error_handler);
+
+ qi::rule<Iterator, ast::expression(), ascii::space_type> expr;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> additive_expr;
+ qi::rule<Iterator, ast::expression(), ascii::space_type> multiplicative_expr;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> unary_expr;
+ qi::rule<Iterator, ast::operand(), ascii::space_type> primary_expr;
+ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp
new file mode 100644
index 00000000..2770677c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/expression_def.hpp
@@ -0,0 +1,94 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
+ : expression::base_type(expr)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ expr =
+ additive_expr.alias()
+ ;
+
+ additive_expr =
+ multiplicative_expr
+ >> *( (char_('+') > multiplicative_expr)
+ | (char_('-') > multiplicative_expr)
+ )
+ ;
+
+ multiplicative_expr =
+ unary_expr
+ >> *( (char_('*') > unary_expr)
+ | (char_('/') > unary_expr)
+ )
+ ;
+
+ unary_expr =
+ primary_expr
+ | (char_('-') > primary_expr)
+ | (char_('+') > primary_expr)
+ ;
+
+ primary_expr =
+ uint_
+ | identifier
+ | '(' > expr > ')'
+ ;
+
+ identifier =
+ raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (additive_expr)
+ (multiplicative_expr)
+ (unary_expr)
+ (primary_expr)
+ (identifier)
+ );
+
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp
new file mode 100644
index 00000000..4e139eb2
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/main.cpp
@@ -0,0 +1,101 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Now we'll introduce variables and assignment. This time, we'll also
+// be renaming some of the rules -- a strategy for a grander scheme
+// to come ;-)
+//
+// This version also shows off grammar modularization. Here you will
+// see how expressions and statements are built as modular grammars.
+//
+// [ JDG April 9, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "statement.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Statement parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type some statements... ";
+ std::cout << "An empty line ends input, compiles, runs and prints results\n\n";
+ std::cout << "Example:\n\n";
+ std::cout << " var a = 123;\n";
+ std::cout << " var b = 456;\n";
+ std::cout << " var c = a + b * 2;\n\n";
+ std::cout << "-------------------------\n";
+
+ std::string str;
+ std::string source;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+ source += str + '\n';
+ }
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source.begin();
+ iterator_type end = source.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::code_gen::program program; // Our VM program
+ client::ast::statement_list ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::parser::statement<iterator_type>
+ parser(error_handler); // Our parser
+ client::code_gen::compiler
+ compile(program, error_handler); // Our compiler
+
+ boost::spirit::ascii::space_type space;
+ bool success = phrase_parse(iter, end, parser, space, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compile(ast))
+ {
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ vm.execute(program());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ program.print_assembler();
+
+ std::cout << "-------------------------\n";
+ std::cout << "Results------------------\n\n";
+ program.print_variables(vm.get_stack());
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+
+ std::cout << "-------------------------\n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp
new file mode 100644
index 00000000..54bc9ac3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::statement<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp
new file mode 100644
index 00000000..12baf38f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_STATEMENT_HPP)
+#define BOOST_SPIRIT_CALC7_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement_list(), ascii::space_type>
+ {
+ statement(error_handler<Iterator>& error_handler);
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement_list(), ascii::space_type> statement_list;
+ qi::rule<Iterator, ast::variable_declaration(), ascii::space_type> variable_declaration;
+ qi::rule<Iterator, ast::assignment(), ascii::space_type> assignment;
+ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp
new file mode 100644
index 00000000..408a2368
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/statement_def.hpp
@@ -0,0 +1,75 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(statement_list), expr(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +(variable_declaration | assignment)
+ ;
+
+ identifier =
+ raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ lexeme["var" >> !(alnum | '_')] // make sure we have whole words
+ > assignment
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (identifier)
+ (variable_declaration)
+ (assignment)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in assignment, call annotation.
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.cpp
new file mode 100644
index 00000000..c481f2b7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.cpp
@@ -0,0 +1,66 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "vm.hpp"
+
+namespace client
+{
+ void vmachine::execute(std::vector<int> const& code)
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+ std::vector<int>::iterator locals = stack.begin();
+ stack_ptr = stack.begin();
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_load:
+ *stack_ptr++ = locals[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ locals[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_stk_adj:
+ stack_ptr = stack.begin() + *pc++;
+ break;
+ }
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp
new file mode 100644
index 00000000..853aa9c7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc7/vm.hpp
@@ -0,0 +1,52 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC7_VM_HPP)
+#define BOOST_SPIRIT_CALC7_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+ op_int, // push constant integer into the stack
+ op_stk_adj // adjust the stack for local variables
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ void execute(std::vector<int> const& code);
+ std::vector<int> const& get_stack() const { return stack; };
+
+ private:
+
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/annotation.hpp
new file mode 100644
index 00000000..8cd00973
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/annotation.hpp
@@ -0,0 +1,78 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CALC8_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ this->dispatch(x, boost::is_base_of<ast::tagged, T>());
+ }
+
+ // This will catch all nodes except those inheriting from ast::tagged
+ template <typename T>
+ void dispatch(T& x, boost::mpl::false_) const
+ {
+ // (no-op) no need for tags
+ }
+
+ // This will catch all nodes inheriting from ast::tagged
+ template <typename T>
+ void dispatch(T& x, boost::mpl::true_) const
+ {
+ x.id = id;
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/ast.hpp
new file mode 100644
index 00000000..3e6e2d79
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/ast.hpp
@@ -0,0 +1,172 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_AST_HPP)
+#define BOOST_SPIRIT_CALC8_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct expression;
+
+ struct variable : tagged
+ {
+ variable(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , variable
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ enum optoken
+ {
+ op_plus,
+ op_minus,
+ op_times,
+ op_divide,
+ op_positive,
+ op_negative,
+ op_not,
+ op_equal,
+ op_not_equal,
+ op_less,
+ op_less_equal,
+ op_greater,
+ op_greater_equal,
+ op_and,
+ op_or
+ };
+
+ struct unary
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ variable lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ assignment assign;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+ inline std::ostream& operator<<(std::ostream& out, variable const& var) { out << var.name; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::assignment, assign)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::variable, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp
new file mode 100644
index 00000000..2d8b3eb1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.cpp
@@ -0,0 +1,382 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void program::op(int a)
+ {
+ code.push_back(a);
+ }
+
+ void program::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ }
+
+ void program::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ }
+
+ int const* program::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void program::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void program::print_variables(std::vector<int> const& stack) const
+ {
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
+ }
+ }
+
+ void program::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << " local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != code.end())
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ typedef std::pair<std::size_t, std::string> line_info;
+ BOOST_FOREACH(line_info const& l, lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x) const
+ {
+ program.op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x) const
+ {
+ program.op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable const& x) const
+ {
+ int const* p = program.find_var(x.name);
+ if (p == 0)
+ {
+ std::cout << x.id << std::endl;
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ program.op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::operation const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_plus: program.op(op_add); break;
+ case ast::op_minus: program.op(op_sub); break;
+ case ast::op_times: program.op(op_mul); break;
+ case ast::op_divide: program.op(op_div); break;
+
+ case ast::op_equal: program.op(op_eq); break;
+ case ast::op_not_equal: program.op(op_neq); break;
+ case ast::op_less: program.op(op_lt); break;
+ case ast::op_less_equal: program.op(op_lte); break;
+ case ast::op_greater: program.op(op_gt); break;
+ case ast::op_greater_equal: program.op(op_gte); break;
+
+ case ast::op_and: program.op(op_and); break;
+ case ast::op_or: program.op(op_or); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_negative: program.op(op_neg); break;
+ case ast::op_not: program.op(op_not); break;
+ case ast::op_positive: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ BOOST_FOREACH(ast::operation const& oper, x.rest)
+ {
+ if (!(*this)(oper))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x) const
+ {
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = program.find_var(x.lhs.name);
+ if (p == 0)
+ {
+ std::cout << x.lhs.id << std::endl;
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ program.op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x) const
+ {
+ int const* p = program.find_var(x.assign.lhs.name);
+ if (p != 0)
+ {
+ std::cout << x.assign.lhs.id << std::endl;
+ error_handler(x.assign.lhs.id, "Duplicate variable: " + x.assign.lhs.name);
+ return false;
+ }
+ bool r = (*this)(x.assign.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ program.add_var(x.assign.lhs.name);
+ program.op(op_store, *program.find_var(x.assign.lhs.name));
+ }
+ return r;
+ }
+
+ bool compiler::operator()(ast::statement const& x) const
+ {
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x) const
+ {
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x) const
+ {
+ if (!(*this)(x.condition))
+ return false;
+ program.op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = program.size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ program[skip] = program.size()-skip; // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an alse
+ {
+ program[skip] += 2; // adjust for the "else" jump
+ program.op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = program.size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ program[exit] = program.size()-exit; // now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x) const
+ {
+ std::size_t loop = program.size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ program.op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = program.size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ program.op(op_jump,
+ int(loop-1) - int(program.size())); // loop back
+ program[exit] = program.size()-exit; // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::start(ast::statement_list const& x) const
+ {
+ program.clear();
+ // op_stk_adj 0 for now. we'll know how many variables we'll have later
+ program.op(op_stk_adj, 0);
+
+ if (!(*this)(x))
+ {
+ program.clear();
+ return false;
+ }
+ program[1] = program.nvars(); // now store the actual number of variables
+ return true;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.hpp
new file mode 100644
index 00000000..915a87d0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/compiler.hpp
@@ -0,0 +1,92 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_COMPILER_HPP)
+#define BOOST_SPIRIT_CALC8_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Program
+ ///////////////////////////////////////////////////////////////////////////
+ struct program
+ {
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[i]; }
+ int const& operator[](std::size_t i) const { return code[i]; }
+ void clear() { code.clear(); variables.clear(); }
+ std::size_t size() const { return code.size(); }
+ std::vector<int> const& operator()() const { return code; }
+
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+
+ void print_variables(std::vector<int> const& stack) const;
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::vector<int> code;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(client::code_gen::program& program, ErrorHandler& error_handler_)
+ : program(program)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) const { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x) const;
+ bool operator()(bool x) const;
+ bool operator()(ast::variable const& x) const;
+ bool operator()(ast::operation const& x) const;
+ bool operator()(ast::unary const& x) const;
+ bool operator()(ast::expression const& x) const;
+ bool operator()(ast::assignment const& x) const;
+ bool operator()(ast::variable_declaration const& x) const;
+ bool operator()(ast::statement_list const& x) const;
+ bool operator()(ast::statement const& x) const;
+ bool operator()(ast::if_statement const& x) const;
+ bool operator()(ast::while_statement const& x) const;
+
+ bool start(ast::statement_list const& x) const;
+
+ client::code_gen::program& program;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/error_handler.hpp
new file mode 100644
index 00000000..0cc42ca9
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/error_handler.hpp
@@ -0,0 +1,93 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CALC8_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ if (err_pos != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.cpp
new file mode 100644
index 00000000..32f44adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::expression<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.hpp
new file mode 100644
index 00000000..e5770bb1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression.hpp
@@ -0,0 +1,68 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CALC8_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct expression : qi::grammar<Iterator, ast::expression(), ascii::space_type>
+ {
+ expression(error_handler<Iterator>& error_handler);
+
+ qi::rule<Iterator, ast::expression(), ascii::space_type>
+ expr, equality_expr, relational_expr,
+ logical_expr, additive_expr, multiplicative_expr
+ ;
+
+ qi::rule<Iterator, ast::operand(), ascii::space_type>
+ unary_expr, primary_expr
+ ;
+
+ qi::rule<Iterator, std::string(), ascii::space_type>
+ identifier
+ ;
+
+ qi::symbols<char, ast::optoken>
+ equality_op, relational_op, logical_op,
+ additive_op, multiplicative_op, unary_op
+ ;
+
+ qi::symbols<char>
+ keywords
+ ;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression_def.hpp
new file mode 100644
index 00000000..608992c3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/expression_def.hpp
@@ -0,0 +1,159 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
+ : expression::base_type(expr)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::bool_type bool_;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tokens
+ logical_op.add
+ ("&&", ast::op_and)
+ ("||", ast::op_or)
+ ;
+
+ equality_op.add
+ ("==", ast::op_equal)
+ ("!=", ast::op_not_equal)
+ ;
+
+ relational_op.add
+ ("<", ast::op_less)
+ ("<=", ast::op_less_equal)
+ (">", ast::op_greater)
+ (">=", ast::op_greater_equal)
+ ;
+
+ additive_op.add
+ ("+", ast::op_plus)
+ ("-", ast::op_minus)
+ ;
+
+ multiplicative_op.add
+ ("*", ast::op_times)
+ ("/", ast::op_divide)
+ ;
+
+ unary_op.add
+ ("+", ast::op_positive)
+ ("-", ast::op_negative)
+ ("!", ast::op_not)
+ ;
+
+ keywords.add
+ ("var")
+ ("true")
+ ("false")
+ ("if")
+ ("else")
+ ("while")
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ logical_expr.alias()
+ ;
+
+ logical_expr =
+ equality_expr
+ >> *(logical_op > equality_expr)
+ ;
+
+ equality_expr =
+ relational_expr
+ >> *(equality_op > relational_expr)
+ ;
+
+ relational_expr =
+ additive_expr
+ >> *(relational_op > additive_expr)
+ ;
+
+ additive_expr =
+ multiplicative_expr
+ >> *(additive_op > multiplicative_expr)
+ ;
+
+ multiplicative_expr =
+ unary_expr
+ >> *(multiplicative_op > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (unary_op > primary_expr)
+ ;
+
+ primary_expr =
+ uint_
+ | identifier
+ | bool_
+ | '(' > expr > ')'
+ ;
+
+ identifier =
+ !keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (equality_expr)
+ (relational_expr)
+ (logical_expr)
+ (additive_expr)
+ (multiplicative_expr)
+ (unary_expr)
+ (primary_expr)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/main.cpp
new file mode 100644
index 00000000..9c3b7346
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/main.cpp
@@ -0,0 +1,97 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Now we'll introduce boolean expressions and control structures.
+// Is it obvious now what we are up to? ;-)
+//
+// [ JDG April 9, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "statement.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Statement parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type some statements... ";
+ std::cout << "An empty line ends input, compiles, runs and prints results\n\n";
+ std::cout << "Example:\n\n";
+ std::cout << " var a = 123;\n";
+ std::cout << " var b = 456;\n";
+ std::cout << " var c = a + b * 2;\n\n";
+ std::cout << "-------------------------\n";
+
+ std::string str;
+ std::string source;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+ source += str + '\n';
+ }
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source.begin();
+ iterator_type end = source.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::code_gen::program program; // Our VM program
+ client::ast::statement_list ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::parser::statement<iterator_type>
+ parser(error_handler); // Our parser
+ client::code_gen::compiler
+ compile(program, error_handler); // Our compiler
+
+ boost::spirit::ascii::space_type space;
+ bool success = phrase_parse(iter, end, parser, space, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compile.start(ast))
+ {
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ vm.execute(program());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ program.print_assembler();
+
+ std::cout << "-------------------------\n";
+ std::cout << "Results------------------\n\n";
+ program.print_variables(vm.stack);
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+
+ std::cout << "-------------------------\n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.cpp
new file mode 100644
index 00000000..54bc9ac3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::statement<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.hpp
new file mode 100644
index 00000000..8b6c6b77
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement.hpp
@@ -0,0 +1,37 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_STATEMENT_HPP)
+#define BOOST_SPIRIT_CALC8_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement_list(), ascii::space_type>
+ {
+ statement(error_handler<Iterator>& error_handler);
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement_list(), ascii::space_type>
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement(), ascii::space_type> statement_;
+ qi::rule<Iterator, ast::variable_declaration(), ascii::space_type> variable_declaration;
+ qi::rule<Iterator, ast::assignment(), ascii::space_type> assignment;
+ qi::rule<Iterator, ast::if_statement(), ascii::space_type> if_statement;
+ qi::rule<Iterator, ast::while_statement(), ascii::space_type> while_statement;
+ qi::rule<Iterator, std::string(), ascii::space_type> identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement_def.hpp
new file mode 100644
index 00000000..d007ac06
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/statement_def.hpp
@@ -0,0 +1,111 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(statement_list), expr(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::lit_type lit;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ ;
+
+ identifier =
+ !expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ lexeme["var" >> !(alnum | '_')] // make sure we have whole words
+ > &identifier // expect an identifier
+ > assignment
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ lit("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ lexeme["else" >> !(alnum | '_')] // make sure we have whole words
+ > statement_
+ )
+ ;
+
+ while_statement =
+ lit("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (identifier)
+ (variable_declaration)
+ (assignment)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in assignment, call annotation.
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp
new file mode 100644
index 00000000..70589fa1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.cpp
@@ -0,0 +1,163 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "vm.hpp"
+#include <boost/assert.hpp>
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (pc != code.end())
+ {
+ BOOST_ASSERT(pc != code.end());
+
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr = stack.begin() + *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ return -1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.hpp
new file mode 100644
index 00000000..bab387f7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/calc8/vm.hpp
@@ -0,0 +1,77 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CALC8_VM_HPP)
+#define BOOST_SPIRIT_CALC8_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ };
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/annotation.hpp
new file mode 100644
index 00000000..2361a7f4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/annotation.hpp
@@ -0,0 +1,95 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CONJURE_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ void operator()(ast::identifier& x) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ // no-op
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::variable_declaration& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/ast.hpp
new file mode 100644
index 00000000..e5022472
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/ast.hpp
@@ -0,0 +1,275 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_AST_HPP)
+#define BOOST_SPIRIT_CONJURE_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<function_call>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ enum optoken
+ {
+ // precedence 1
+ op_comma,
+
+ // precedence 2
+ op_assign,
+ op_plus_assign,
+ op_minus_assign,
+ op_times_assign,
+ op_divide_assign,
+ op_mod_assign,
+ op_bit_and_assign,
+ op_bit_xor_assign,
+ op_bitor_assign,
+ op_shift_left_assign,
+ op_shift_right_assign,
+
+ // precedence 3
+ op_logical_or,
+
+ // precedence 4
+ op_logical_and,
+
+ // precedence 5
+ op_bit_or,
+
+ // precedence 6
+ op_bit_xor,
+
+ // precedence 7
+ op_bit_and,
+
+ // precedence 8
+ op_equal,
+ op_not_equal,
+
+ // precedence 9
+ op_less,
+ op_less_equal,
+ op_greater,
+ op_greater_equal,
+
+ // precedence 10
+ op_shift_left,
+ op_shift_right,
+
+ // precedence 11
+ op_plus,
+ op_minus,
+
+ // precedence 12
+ op_times,
+ op_divide,
+ op_mod,
+
+ // precedence 13
+ op_positive,
+ op_negative,
+ op_pre_incr,
+ op_pre_decr,
+ op_compl,
+ op_not,
+
+ // precedence 14
+ op_post_incr,
+ op_post_decr,
+ };
+
+ struct unary
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ statement_list body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (client::ast::statement_list, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.cpp
new file mode 100644
index 00000000..22a036d4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.cpp
@@ -0,0 +1,628 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void function::op(int a)
+ {
+ code.push_back(a);
+ size_ += 1;
+ }
+
+ void function::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ size_ += 2;
+ }
+
+ void function::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ size_ += 3;
+ }
+
+ int const* function::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void function::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void function::link_to(std::string const& name, std::size_t address)
+ {
+ function_calls[address] = name;
+ }
+
+ void function::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin() + address;
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << " local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != (code.begin() + address + size_))
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_call:
+ {
+ line += " op_call ";
+ int nargs = *pc++;
+ std::size_t jump = *pc++;
+ line += boost::lexical_cast<std::string>(nargs) + ", ";
+ BOOST_ASSERT(function_calls.find(jump) != function_calls.end());
+ line += function_calls.find(jump)->second;
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+
+ case op_return:
+ line += " op_return";
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ typedef std::pair<std::size_t, std::string> line_info;
+ BOOST_FOREACH(line_info const& l, lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::identifier const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.name);
+ if (p == 0)
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ current->op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::optoken const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ switch (x)
+ {
+ case ast::op_plus: current->op(op_add); break;
+ case ast::op_minus: current->op(op_sub); break;
+ case ast::op_times: current->op(op_mul); break;
+ case ast::op_divide: current->op(op_div); break;
+
+ case ast::op_equal: current->op(op_eq); break;
+ case ast::op_not_equal: current->op(op_neq); break;
+ case ast::op_less: current->op(op_lt); break;
+ case ast::op_less_equal: current->op(op_lte); break;
+ case ast::op_greater: current->op(op_gt); break;
+ case ast::op_greater_equal: current->op(op_gte); break;
+
+ case ast::op_logical_or: current->op(op_or); break;
+ case ast::op_logical_and: current->op(op_and); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_negative: current->op(op_neg); break;
+ case ast::op_not: current->op(op_not); break;
+ case ast::op_positive: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_call const& x)
+ {
+ BOOST_ASSERT(current != 0);
+
+ if (functions.find(x.function_name.name) == functions.end())
+ {
+ error_handler(x.function_name.id, "Function not found: " + x.function_name.name);
+ return false;
+ }
+
+ boost::shared_ptr<code_gen::function> p = functions[x.function_name.name];
+
+ if (p->nargs() != x.args.size())
+ {
+ error_handler(x.function_name.id, "Wrong number of arguments: " + x.function_name.name);
+ return false;
+ }
+
+ BOOST_FOREACH(ast::expression const& expr, x.args)
+ {
+ if (!(*this)(expr))
+ return false;
+ }
+
+ current->op(
+ op_call,
+ p->nargs(),
+ p->get_address());
+ current->link_to(x.function_name.name, p->get_address());
+
+ return true;
+ }
+
+ namespace
+ {
+ int precedence[] = {
+ // precedence 1
+ 1, // op_comma
+
+ // precedence 2
+ 2, // op_assign
+ 2, // op_plus_assign
+ 2, // op_minus_assign
+ 2, // op_times_assign
+ 2, // op_divide_assign
+ 2, // op_mod_assign
+ 2, // op_bit_and_assign
+ 2, // op_bit_xor_assign
+ 2, // op_bitor_assign
+ 2, // op_shift_left_assign
+ 2, // op_shift_right_assign
+
+ // precedence 3
+ 3, // op_logical_or
+
+ // precedence 4
+ 4, // op_logical_and
+
+ // precedence 5
+ 5, // op_bit_or
+
+ // precedence 6
+ 6, // op_bit_xor
+
+ // precedence 7
+ 7, // op_bit_and
+
+ // precedence 8
+ 8, // op_equal
+ 8, // op_not_equal
+
+ // precedence 9
+ 9, // op_less
+ 9, // op_less_equal
+ 9, // op_greater
+ 9, // op_greater_equal
+
+ // precedence 10
+ 10, // op_shift_left
+ 10, // op_shift_right
+
+ // precedence 11
+ 11, // op_plus
+ 11, // op_minus
+
+ // precedence 12
+ 12, // op_times
+ 12, // op_divide
+ 12, // op_mod
+
+ // precedence 13
+ 13, // op_positive
+ 13, // op_negative
+ 13, // op_pre_incr
+ 13, // op_pre_decr
+ 13, // op_compl
+ 13, // op_not
+
+ // precedence 14
+ 14, // op_post_incr
+ 14 // op_post_decr
+ };
+ }
+
+ // The Shunting-yard algorithm
+ bool compiler::compile_expression(
+ int min_precedence,
+ std::list<ast::operation>::const_iterator& rbegin,
+ std::list<ast::operation>::const_iterator rend)
+ {
+ while ((rbegin != rend) && (precedence[rbegin->operator_] >= min_precedence))
+ {
+ ast::optoken op = rbegin->operator_;
+ if (!boost::apply_visitor(*this, rbegin->operand_))
+ return false;
+ ++rbegin;
+
+ while ((rbegin != rend) && (precedence[rbegin->operator_] > precedence[op]))
+ {
+ ast::optoken next_op = rbegin->operator_;
+ compile_expression(precedence[next_op], rbegin, rend);
+ }
+ (*this)(op);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ std::list<ast::operation>::const_iterator rbegin = x.rest.begin();
+ if (!compile_expression(0, rbegin, x.rest.end()))
+ return false;
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = current->find_var(x.lhs.name);
+ if (p == 0)
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ current->op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.lhs.name);
+ if (p != 0)
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+ if (x.rhs) // if there's an RHS initializer
+ {
+ bool r = (*this)(*x.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ current->add_var(x.lhs.name);
+ current->op(op_store, *current->find_var(x.lhs.name));
+ }
+ return r;
+ }
+ else
+ {
+ current->add_var(x.lhs.name);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = current->size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ (*current)[skip] = current->size()-skip; // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an alse
+ {
+ (*current)[skip] += 2; // adjust for the "else" jump
+ current->op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ (*current)[exit] = current->size()-exit;// now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ std::size_t loop = current->size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ current->op(op_jump,
+ int(loop-1) - int(current->size())); // loop back
+ (*current)[exit] = current->size()-exit; // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(x.id, current_function_name + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ if (!(*this)(*x.expr))
+ return false;
+ }
+ current->op(op_return);
+ return true;
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ if (functions.find(x.function_name.name) != functions.end())
+ {
+ error_handler(x.function_name.id, "Duplicate function: " + x.function_name.name);
+ return false;
+ }
+ boost::shared_ptr<code_gen::function>& p = functions[x.function_name.name];
+ p.reset(new code_gen::function(code, x.args.size()));
+ current = p.get();
+ current_function_name = x.function_name.name;
+
+ // op_stk_adj 0 for now. we'll know how many variables
+ // we'll have later and add them
+ current->op(op_stk_adj, 0);
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ current->add_var(arg.name);
+ }
+
+ if (!(*this)(x.body))
+ return false;
+ (*current)[1] = current->nvars(); // now store the actual number of variables
+ // this includes the arguments
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ // Jump to the main function
+ code.push_back(op_jump);
+ code.push_back(0); // we will fill this in later when we finish compiling
+ // and we know where the main function is
+
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ if (!(*this)(f))
+ {
+ code.clear();
+ return false;
+ }
+ }
+ // find the main function
+ boost::shared_ptr<code_gen::function> p =
+ find_function("main");
+
+ if (!p) // main function not found
+ {
+ std::cerr << "Error: main function not defined" << std::endl;
+ return false;
+ }
+ code[1] = p->get_address()-1; // jump to this (main function) address
+
+ return true;
+ }
+
+ void compiler::print_assembler() const
+ {
+ typedef std::pair<std::string, boost::shared_ptr<code_gen::function> > pair;
+ BOOST_FOREACH(pair const& p, functions)
+ {
+ std::cout << ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" << std::endl;
+ std::cout << p.second->get_address() << ": function " << p.first << std::endl;
+ p.second->print_assembler();
+ }
+ }
+
+ boost::shared_ptr<code_gen::function>
+ compiler::find_function(std::string const& name) const
+ {
+ function_table::const_iterator i = functions.find(name);
+ if (i == functions.end())
+ return boost::shared_ptr<code_gen::function>();
+ else
+ return i->second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.hpp
new file mode 100644
index 00000000..461f7a7c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/compiler.hpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP)
+#define BOOST_SPIRIT_CONJURE_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Function
+ ///////////////////////////////////////////////////////////////////////////
+ struct function
+ {
+ function(std::vector<int>& code, int nargs)
+ : code(code), address(code.size()), size_(0), nargs_(nargs) {}
+
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[address+i]; }
+ int const& operator[](std::size_t i) const { return code[address+i]; }
+ std::size_t size() const { return size_; }
+ std::size_t get_address() const { return address; }
+
+ int nargs() const { return nargs_; }
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+ void link_to(std::string const& name, std::size_t address);
+
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::map<std::size_t, std::string> function_calls;
+ std::vector<int>& code;
+ std::size_t address;
+ std::size_t size_;
+ std::size_t nargs_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(ErrorHandler& error_handler_)
+ : current(0)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x);
+ bool operator()(bool x);
+ bool operator()(ast::identifier const& x);
+ bool operator()(ast::optoken const& x);
+ bool operator()(ast::unary const& x);
+ bool operator()(ast::function_call const& x);
+ bool operator()(ast::expression const& x);
+ bool operator()(ast::assignment const& x);
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ void print_assembler() const;
+
+ boost::shared_ptr<code_gen::function>
+ find_function(std::string const& name) const;
+
+ std::vector<int>& get_code() { return code; }
+ std::vector<int> const& get_code() const { return code; }
+
+ private:
+
+ bool compile_expression(
+ int min_precedence,
+ std::list<ast::operation>::const_iterator& rbegin,
+ std::list<ast::operation>::const_iterator rend);
+
+ typedef std::map<std::string, boost::shared_ptr<code_gen::function> > function_table;
+
+ std::vector<int> code;
+ code_gen::function* current;
+ std::string current_function_name;
+ function_table functions;
+ bool void_return;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/error_handler.hpp
new file mode 100644
index 00000000..2c1aa44e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/error_handler.hpp
@@ -0,0 +1,93 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ if (err_pos != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.cpp
new file mode 100644
index 00000000..32f44adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::expression<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.hpp
new file mode 100644
index 00000000..985b972c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression.hpp
@@ -0,0 +1,75 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CONJURE_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include "skipper.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct expression : qi::grammar<Iterator, ast::expression(), skipper<Iterator> >
+ {
+ expression(error_handler<Iterator>& error_handler);
+
+ qi::rule<Iterator, ast::expression(), skipper<Iterator> >
+ expr
+ ;
+
+ qi::rule<Iterator, ast::operand(), skipper<Iterator> >
+ unary_expr, primary_expr
+ ;
+
+ qi::rule<Iterator, ast::function_call(), skipper<Iterator> >
+ function_call
+ ;
+
+ qi::rule<Iterator, std::list<ast::expression>(), skipper<Iterator> >
+ argument_list
+ ;
+
+ qi::rule<Iterator, std::string(), skipper<Iterator> >
+ identifier
+ ;
+
+ qi::symbols<char, ast::optoken>
+ unary_op, binary_op
+ ;
+
+ qi::symbols<char>
+ keywords
+ ;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression_def.hpp
new file mode 100644
index 00000000..21ccc9bd
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/expression_def.hpp
@@ -0,0 +1,131 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
+ : expression::base_type(expr)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::bool_type bool_;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tokens
+ binary_op.add
+ ("||", ast::op_logical_or)
+ ("&&", ast::op_logical_and)
+ ("==", ast::op_equal)
+ ("!=", ast::op_not_equal)
+ ("<", ast::op_less)
+ ("<=", ast::op_less_equal)
+ (">", ast::op_greater)
+ (">=", ast::op_greater_equal)
+ ("+", ast::op_plus)
+ ("-", ast::op_minus)
+ ("*", ast::op_times)
+ ("/", ast::op_divide)
+ ;
+
+ unary_op.add
+ ("+", ast::op_positive)
+ ("-", ast::op_negative)
+ ("!", ast::op_not)
+ ;
+
+ keywords.add
+ ("true")
+ ("false")
+ ("if")
+ ("else")
+ ("while")
+ ("int")
+ ("void")
+ ("return")
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ unary_expr
+ >> *(binary_op > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (unary_op > unary_expr)
+ ;
+
+ primary_expr =
+ uint_
+ | function_call
+ | identifier
+ | bool_
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier =
+ !lexeme[keywords >> !(alnum | '_')]
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (unary_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.cpp
new file mode 100644
index 00000000..ababd4ad
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "function_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::function<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.hpp
new file mode 100644
index 00000000..9eddd66c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_FUNCTION_HPP)
+#define BOOST_SPIRIT_CONJURE_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct function : qi::grammar<Iterator, ast::function(), skipper<Iterator> >
+ {
+ function(error_handler<Iterator>& error_handler);
+
+ statement<Iterator> body;
+ qi::rule<Iterator, std::string(), skipper<Iterator> > name;
+ qi::rule<Iterator, ast::identifier(), skipper<Iterator> > identifier;
+ qi::rule<Iterator, std::list<ast::identifier>(), skipper<Iterator> > argument_list;
+ qi::rule<Iterator, ast::function(), skipper<Iterator> > start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function_def.hpp
new file mode 100644
index 00000000..bd2c7d02
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/function_def.hpp
@@ -0,0 +1,71 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ function<Iterator>::function(error_handler<Iterator>& error_handler)
+ : function::base_type(start), body(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::string_type string;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ name =
+ !body.expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ identifier = name;
+ argument_list = -(identifier % ',');
+
+ start =
+ lexeme[(string("void") | string("int"))
+ >> !(alnum | '_')] // make sure we have whole words
+ > identifier
+ > '(' > argument_list > ')'
+ > '{' > body > '}'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/main.cpp
new file mode 100644
index 00000000..8b2a8007
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/main.cpp
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "function.hpp"
+#include "skipper.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source_code.begin();
+ iterator_type end = source_code.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::parser::function<iterator_type>
+ function(error_handler); // Our parser
+ client::parser::skipper<iterator_type>
+ skipper; // Our skipper
+ client::code_gen::compiler
+ compiler(error_handler); // Our compiler
+
+
+ bool success = phrase_parse(iter, end, +function, skipper, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ boost::shared_ptr<client::code_gen::function>
+ p = compiler.find_function("main");
+ if (!p)
+ return 1;
+
+ int nargs = argc-2;
+ if (p->nargs() != nargs)
+ {
+ std::cerr << "Error: main function requires " << p->nargs() << " arguments." << std::endl;
+ std::cerr << nargs << " supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ compiler.print_assembler();
+
+ // Push the arguments into our stack
+ for (int i = 0; i < nargs; ++i)
+ vm.get_stack()[i] = boost::lexical_cast<int>(argv[i+2]);
+
+ // Call the interpreter
+ int r = vm.execute(compiler.get_code());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/skipper.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/skipper.hpp
new file mode 100644
index 00000000..bb1acc21
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/skipper.hpp
@@ -0,0 +1,40 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_SKIPPER_HPP)
+#define BOOST_SPIRIT_CONJURE_SKIPPER_HPP
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The skipper grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct skipper : qi::grammar<Iterator>
+ {
+ skipper() : skipper::base_type(start)
+ {
+ qi::char_type char_;
+ ascii::space_type space;
+
+ start =
+ space // tab/space/cr/lf
+ | "/*" >> *(char_ - "*/") >> "*/" // C-style comments
+ ;
+ }
+
+ qi::rule<Iterator> start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.cpp
new file mode 100644
index 00000000..54bc9ac3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::statement<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.hpp
new file mode 100644
index 00000000..72485cbf
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement.hpp
@@ -0,0 +1,38 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_STATEMENT_HPP)
+#define BOOST_SPIRIT_CONJURE_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement_list(), skipper<Iterator> >
+ {
+ statement(error_handler<Iterator>& error_handler);
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement_list(), skipper<Iterator> >
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement(), skipper<Iterator> > statement_;
+ qi::rule<Iterator, ast::variable_declaration(), skipper<Iterator> > variable_declaration;
+ qi::rule<Iterator, ast::assignment(), skipper<Iterator> > assignment;
+ qi::rule<Iterator, ast::if_statement(), skipper<Iterator> > if_statement;
+ qi::rule<Iterator, ast::while_statement(), skipper<Iterator> > while_statement;
+ qi::rule<Iterator, ast::return_statement(), skipper<Iterator> > return_statement;
+ qi::rule<Iterator, std::string(), skipper<Iterator> > identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement_def.hpp
new file mode 100644
index 00000000..29e40942
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/statement_def.hpp
@@ -0,0 +1,128 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(statement_list), expr(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::lit_type lit;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ ;
+
+ identifier =
+ !expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ lexeme["int" >> !(alnum | '_')] // make sure we have whole words
+ > identifier
+ > -('=' > expr)
+ > ';'
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ lit("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ lexeme["else" >> !(alnum | '_')] // make sure we have whole words
+ > statement_
+ )
+ ;
+
+ while_statement =
+ lit("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ lexeme["return" >> !(alnum | '_')] // make sure we have whole words
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (statement_)
+ (variable_declaration)
+ (assignment)
+ (if_statement)
+ (while_statement)
+ (compound_statement)
+ (return_statement)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in variable_declaration,
+ // assignment and return_statement, call annotation.
+ on_success(variable_declaration,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.cpp
new file mode 100644
index 00000000..8740bf9c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.cpp
@@ -0,0 +1,159 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "vm.hpp"
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (true)
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr += *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.hpp
new file mode 100644
index 00000000..0362eaf8
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure1/vm.hpp
@@ -0,0 +1,82 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_VM_HPP)
+#define BOOST_SPIRIT_CONJURE_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ }
+
+ std::vector<int> const& get_stack() const { return stack; };
+ std::vector<int>& get_stack() { return stack; };
+
+ private:
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/annotation.hpp
new file mode 100644
index 00000000..2361a7f4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/annotation.hpp
@@ -0,0 +1,95 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CONJURE_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ void operator()(ast::identifier& x) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ // no-op
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::variable_declaration& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ast.hpp
new file mode 100644
index 00000000..d2f893b0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ast.hpp
@@ -0,0 +1,209 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_AST_HPP)
+#define BOOST_SPIRIT_CONJURE_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+#include "ids.hpp"
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<function_call>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ struct unary
+ {
+ token_ids::type operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ token_ids::type operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ statement_list body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::token_ids::type, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::token_ids::type, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (client::ast::statement_list, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.cpp
new file mode 100644
index 00000000..87459b35
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.cpp
@@ -0,0 +1,622 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "config.hpp"
+#include "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void function::op(int a)
+ {
+ code.push_back(a);
+ size_ += 1;
+ }
+
+ void function::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ size_ += 2;
+ }
+
+ void function::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ size_ += 3;
+ }
+
+ int const* function::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void function::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void function::link_to(std::string const& name, std::size_t address)
+ {
+ function_calls[address] = name;
+ }
+
+ void function::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin() + address;
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << " local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != (code.begin() + address + size_))
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_call:
+ {
+ line += " op_call ";
+ int nargs = *pc++;
+ std::size_t jump = *pc++;
+ line += boost::lexical_cast<std::string>(nargs) + ", ";
+ BOOST_ASSERT(function_calls.find(jump) != function_calls.end());
+ line += function_calls.find(jump)->second;
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+
+ case op_return:
+ line += " op_return";
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ typedef std::pair<std::size_t, std::string> line_info;
+ BOOST_FOREACH(line_info const& l, lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::identifier const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.name);
+ if (p == 0)
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ current->op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(token_ids::type const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ switch (x)
+ {
+ case token_ids::plus: current->op(op_add); break;
+ case token_ids::minus: current->op(op_sub); break;
+ case token_ids::times: current->op(op_mul); break;
+ case token_ids::divide: current->op(op_div); break;
+
+ case token_ids::equal: current->op(op_eq); break;
+ case token_ids::not_equal: current->op(op_neq); break;
+ case token_ids::less: current->op(op_lt); break;
+ case token_ids::less_equal: current->op(op_lte); break;
+ case token_ids::greater: current->op(op_gt); break;
+ case token_ids::greater_equal: current->op(op_gte); break;
+
+ case token_ids::logical_or: current->op(op_or); break;
+ case token_ids::logical_and: current->op(op_and); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case token_ids::minus: current->op(op_neg); break;
+ case token_ids::not_: current->op(op_not); break;
+ case token_ids::plus: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_call const& x)
+ {
+ BOOST_ASSERT(current != 0);
+
+ if (functions.find(x.function_name.name) == functions.end())
+ {
+ error_handler(x.function_name.id, "Function not found: " + x.function_name.name);
+ return false;
+ }
+
+ boost::shared_ptr<code_gen::function> p = functions[x.function_name.name];
+
+ if (p->nargs() != x.args.size())
+ {
+ error_handler(x.function_name.id, "Wrong number of arguments: " + x.function_name.name);
+ return false;
+ }
+
+ BOOST_FOREACH(ast::expression const& expr, x.args)
+ {
+ if (!(*this)(expr))
+ return false;
+ }
+
+ current->op(
+ op_call,
+ p->nargs(),
+ p->get_address());
+ current->link_to(x.function_name.name, p->get_address());
+
+ return true;
+ }
+
+ namespace
+ {
+ int precedence[] = {
+ // precedence 1
+ 1, // op_comma
+
+ // precedence 2
+ 2, // op_assign
+ 2, // op_plus_assign
+ 2, // op_minus_assign
+ 2, // op_times_assign
+ 2, // op_divide_assign
+ 2, // op_mod_assign
+ 2, // op_bit_and_assign
+ 2, // op_bit_xor_assign
+ 2, // op_bitor_assign
+ 2, // op_shift_left_assign
+ 2, // op_shift_right_assign
+
+ // precedence 3
+ 3, // op_logical_or
+
+ // precedence 4
+ 4, // op_logical_and
+
+ // precedence 5
+ 5, // op_bit_or
+
+ // precedence 6
+ 6, // op_bit_xor
+
+ // precedence 7
+ 7, // op_bit_and
+
+ // precedence 8
+ 8, // op_equal
+ 8, // op_not_equal
+
+ // precedence 9
+ 9, // op_less
+ 9, // op_less_equal
+ 9, // op_greater
+ 9, // op_greater_equal
+
+ // precedence 10
+ 10, // op_shift_left
+ 10, // op_shift_right
+
+ // precedence 11
+ 11, // op_plus
+ 11, // op_minus
+
+ // precedence 12
+ 12, // op_times
+ 12, // op_divide
+ 12 // op_mod
+ };
+ }
+
+ inline int precedence_of(token_ids::type op)
+ {
+ return precedence[op & 0xFF];
+ }
+
+ // The Shunting-yard algorithm
+ bool compiler::compile_expression(
+ int min_precedence,
+ std::list<ast::operation>::const_iterator& rbegin,
+ std::list<ast::operation>::const_iterator rend)
+ {
+ while ((rbegin != rend) && (precedence_of(rbegin->operator_) >= min_precedence))
+ {
+ token_ids::type op = rbegin->operator_;
+ if (!boost::apply_visitor(*this, rbegin->operand_))
+ return false;
+ ++rbegin;
+
+ while ((rbegin != rend) && (precedence_of(rbegin->operator_) > precedence_of(op)))
+ {
+ token_ids::type next_op = rbegin->operator_;
+ compile_expression(precedence_of(next_op), rbegin, rend);
+ }
+ (*this)(op);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ std::list<ast::operation>::const_iterator rbegin = x.rest.begin();
+ if (!compile_expression(0, rbegin, x.rest.end()))
+ return false;
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = current->find_var(x.lhs.name);
+ if (p == 0)
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ current->op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.lhs.name);
+ if (p != 0)
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+ if (x.rhs) // if there's an RHS initializer
+ {
+ bool r = (*this)(*x.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ current->add_var(x.lhs.name);
+ current->op(op_store, *current->find_var(x.lhs.name));
+ }
+ return r;
+ }
+ else
+ {
+ current->add_var(x.lhs.name);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = current->size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ (*current)[skip] = current->size()-skip; // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an alse
+ {
+ (*current)[skip] += 2; // adjust for the "else" jump
+ current->op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ (*current)[exit] = current->size()-exit;// now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ std::size_t loop = current->size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ current->op(op_jump,
+ int(loop-1) - int(current->size())); // loop back
+ (*current)[exit] = current->size()-exit; // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(x.id, current_function_name + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ if (!(*this)(*x.expr))
+ return false;
+ }
+ current->op(op_return);
+ return true;
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ if (functions.find(x.function_name.name) != functions.end())
+ {
+ error_handler(x.function_name.id, "Duplicate function: " + x.function_name.name);
+ return false;
+ }
+ boost::shared_ptr<code_gen::function>& p = functions[x.function_name.name];
+ p.reset(new code_gen::function(code, x.args.size()));
+ current = p.get();
+ current_function_name = x.function_name.name;
+
+ // op_stk_adj 0 for now. we'll know how many variables
+ // we'll have later and add them
+ current->op(op_stk_adj, 0);
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ current->add_var(arg.name);
+ }
+
+ if (!(*this)(x.body))
+ return false;
+ (*current)[1] = current->nvars(); // now store the actual number of variables
+ // this includes the arguments
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ // Jump to the main function
+ code.push_back(op_jump);
+ code.push_back(0); // we will fill this in later when we finish compiling
+ // and we know where the main function is
+
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ if (!(*this)(f))
+ {
+ code.clear();
+ return false;
+ }
+ }
+ // find the main function
+ boost::shared_ptr<code_gen::function> p =
+ find_function("main");
+
+ if (!p) // main function not found
+ {
+ std::cerr << "Error: main function not defined" << std::endl;
+ return false;
+ }
+ code[1] = p->get_address()-1; // jump to this (main function) address
+
+ return true;
+ }
+
+ void compiler::print_assembler() const
+ {
+ typedef std::pair<std::string, boost::shared_ptr<code_gen::function> > pair;
+ BOOST_FOREACH(pair const& p, functions)
+ {
+ std::cout << ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" << std::endl;
+ std::cout << p.second->get_address() << ": function " << p.first << std::endl;
+ p.second->print_assembler();
+ }
+ }
+
+ boost::shared_ptr<code_gen::function>
+ compiler::find_function(std::string const& name) const
+ {
+ function_table::const_iterator i = functions.find(name);
+ if (i == functions.end())
+ return boost::shared_ptr<code_gen::function>();
+ else
+ return i->second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.hpp
new file mode 100644
index 00000000..b49c0ac4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/compiler.hpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP)
+#define BOOST_SPIRIT_CONJURE_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Function
+ ///////////////////////////////////////////////////////////////////////////
+ struct function
+ {
+ function(std::vector<int>& code, int nargs)
+ : code(code), address(code.size()), size_(0), nargs_(nargs) {}
+
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[address+i]; }
+ int const& operator[](std::size_t i) const { return code[address+i]; }
+ std::size_t size() const { return size_; }
+ std::size_t get_address() const { return address; }
+
+ int nargs() const { return nargs_; }
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+ void link_to(std::string const& name, std::size_t address);
+
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::map<std::size_t, std::string> function_calls;
+ std::vector<int>& code;
+ std::size_t address;
+ std::size_t size_;
+ std::size_t nargs_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(ErrorHandler& error_handler_)
+ : current(0)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x);
+ bool operator()(bool x);
+ bool operator()(ast::identifier const& x);
+ bool operator()(token_ids::type const& x);
+ bool operator()(ast::unary const& x);
+ bool operator()(ast::function_call const& x);
+ bool operator()(ast::expression const& x);
+ bool operator()(ast::assignment const& x);
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ void print_assembler() const;
+
+ boost::shared_ptr<code_gen::function>
+ find_function(std::string const& name) const;
+
+ std::vector<int>& get_code() { return code; }
+ std::vector<int> const& get_code() const { return code; }
+
+ private:
+
+ bool compile_expression(
+ int min_precedence,
+ std::list<ast::operation>::const_iterator& rbegin,
+ std::list<ast::operation>::const_iterator rend);
+
+ typedef std::map<std::string, boost::shared_ptr<code_gen::function> > function_table;
+
+ std::vector<int> code;
+ code_gen::function* current;
+ std::string current_function_name;
+ function_table functions;
+ bool void_return;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/config.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/config.hpp
new file mode 100644
index 00000000..70af0db0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/config.hpp
@@ -0,0 +1,51 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// The conjure lexer example can be built in 3 different variations:
+//
+// - With a lexer using runtime generated DFA tables
+// - With a lexer using pre-generated (static) DFA tables
+// - With a lexer using a pre-generated custom switch based state machine
+//
+// Use one of the following preprocessor constants to define, which of those
+// will be built:
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_DYNAMIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on pre-generated static DFA tables
+// #define CONJURE_LEXER_STATIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_STATIC_SWITCH 1
+
+///////////////////////////////////////////////////////////////////////////////
+// The default is to use the dynamic table driven lexer
+#if CONJURE_LEXER_DYNAMIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_SWITCH == 0
+
+#define CONJURE_LEXER_DYNAMIC_TABLES 1
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Make sure we have only one lexer type selected
+#if (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_TABLES != 0) || \
+ (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0) || \
+ (CONJURE_LEXER_STATIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0)
+
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer.hpp
new file mode 100644
index 00000000..d626840b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer.hpp
@@ -0,0 +1,483 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUL_25_2011_07_03_08)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUL_25_2011_07_03_08
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ enum {end_state_index, id_index, unique_id_index, state_index, bol_index,
+ eol_index, dead_state_index, dfa_offset};
+
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+ static std::size_t const lookup_[256] = {
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 7, 7, 41, 41, 7, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 7, 8, 41, 41, 41, 41, 9, 41,
+ 10, 11, 12, 13, 14, 15, 41, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 41, 19, 20, 21, 22, 41,
+ 41, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 41, 41, 41, 41, 18,
+ 41, 23, 18, 18, 24, 25, 26, 18,
+ 27, 28, 18, 18, 29, 18, 30, 31,
+ 18, 18, 32, 33, 34, 35, 36, 37,
+ 18, 18, 18, 38, 39, 40, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41 };
+ static std::size_t const dfa_alphabet_ = 42;
+ static std::size_t const dfa_[2604] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 27, 13, 11, 20, 21, 18, 16,
+ 24, 17, 19, 2, 26, 25, 14, 12,
+ 15, 26, 26, 7, 4, 26, 6, 26,
+ 26, 26, 9, 26, 3, 26, 5, 8,
+ 22, 10, 23, 0, 1, 35, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 28, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 29,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 30, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 32, 26,
+ 26, 26, 31, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 33, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 34, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 35, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 36, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 61, 26, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 262177, 20, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 39,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131091, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 40, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131093,
+ 14, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 41, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 393241, 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 393242, 17, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131099, 18, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131100,
+ 19, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 42, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 40, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 41, 22, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 123, 23, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 125,
+ 24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 44, 25, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 59, 27, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 34,
+ 30, 0, 0, 0, 0, 27, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 43, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 44,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 45, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 46, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65538, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 47, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 48, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 49, 26, 26, 26, 0, 0, 0, 0,
+ 1, 131084, 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 131085, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131089, 10, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131090,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 131092, 13, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 131094, 15, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 42, 42, 42, 42, 42,
+ 50, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 51,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 43, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 52, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65537, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 53,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 54, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 55, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 56, 56, 56, 56, 56,
+ 50, 56, 56, 56, 57, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 1, 36,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65536, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65539, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 58, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 59, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 33, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 65540, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 61, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 57, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 65541, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0 };
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
+ Iterator curr_ = start_token_;
+ bool end_state_ = *ptr_ != 0;
+ std::size_t id_ = *(ptr_ + id_index);
+ std::size_t uid_ = *(ptr_ + unique_id_index);
+ Iterator end_token_ = start_token_;
+
+ while (curr_ != end_)
+ {
+ std::size_t const state_ =
+ ptr_[lookup_[static_cast<unsigned char>(*curr_++)]];
+
+ if (state_ == 0) break;
+
+ ptr_ = &dfa_[state_ * dfa_alphabet_];
+
+ if (*ptr_)
+ {
+ end_state_ = true;
+ id_ = *(ptr_ + id_index);
+ uid_ = *(ptr_ + unique_id_index);
+ end_token_ = curr_;
+ }
+ }
+
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer_generate.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer_generate.cpp
new file mode 100644
index 00000000..1ba8fac0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_lexer_generate.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This small utility program generates the 2 static lexers, the static table
+// driven and the static switch based lexer.
+
+#include <fstream>
+#include <iostream>
+
+#include "lexer_def.hpp"
+#include <boost/spirit/include/lex_generate_static_lexertl.hpp>
+
+int main()
+{
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+
+ lexer_type lexer;
+
+ // first generate the static switch based lexer
+ std::ofstream out_static("conjure_static_switch_lexer.hpp");
+
+ bool result = boost::spirit::lex::lexertl::generate_static_switch(
+ lexer, out_static, "conjure_static_switch");
+ if (!result) {
+ std::cerr << "Failed to generate static switch based lexer\n";
+ return -1;
+ }
+
+ // now generate the static table based lexer
+ std::ofstream out("conjure_static_lexer.hpp");
+ result = boost::spirit::lex::lexertl::generate_static(
+ lexer, out, "conjure_static");
+ if (!result) {
+ std::cerr << "Failed to generate static table based lexer\n";
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_switch_lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_switch_lexer.hpp
new file mode 100644
index 00000000..3b23016b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/conjure_static_switch_lexer.hpp
@@ -0,0 +1,873 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUL_25_2011_07_03_08)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUL_25_2011_07_03_08
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static_switch[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static_switch = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static_switch (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ Iterator curr_ = start_token_;
+ bool end_state_ = false;
+ std::size_t id_ = npos;
+ std::size_t uid_ = npos;
+ Iterator end_token_ = start_token_;
+
+ char ch_ = 0;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+
+ if (ch_ == 't') goto state0_2;
+
+ if (ch_ == 'f') goto state0_3;
+
+ if (ch_ == 'v') goto state0_4;
+
+ if (ch_ == 'i') goto state0_5;
+
+ if (ch_ == 'e') goto state0_6;
+
+ if (ch_ == 'w') goto state0_7;
+
+ if (ch_ == 'r') goto state0_8;
+
+ if (ch_ == '|') goto state0_9;
+
+ if (ch_ == '&') goto state0_10;
+
+ if (ch_ == '=') goto state0_11;
+
+ if (ch_ == '!') goto state0_12;
+
+ if (ch_ == '<') goto state0_13;
+
+ if (ch_ == '>') goto state0_14;
+
+ if (ch_ == '+') goto state0_15;
+
+ if (ch_ == '-') goto state0_16;
+
+ if (ch_ == '*') goto state0_17;
+
+ if (ch_ == '/') goto state0_18;
+
+ if (ch_ == '(') goto state0_19;
+
+ if (ch_ == ')') goto state0_20;
+
+ if (ch_ == '{') goto state0_21;
+
+ if (ch_ == '}') goto state0_22;
+
+ if (ch_ == ',') goto state0_23;
+
+ if (ch_ == ';') goto state0_24;
+
+ if ((ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'g' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'q') || ch_ == 's' || ch_ == 'u' || (ch_ >= 'x' && ch_ <= 'z')) goto state0_25;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_1:
+ end_state_ = true;
+ id_ = 35;
+ uid_ = 0;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+ goto end;
+
+state0_2:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_27;
+ goto end;
+
+state0_3:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'b' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'a') goto state0_28;
+ goto end;
+
+state0_4:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'n') || (ch_ >= 'p' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'o') goto state0_29;
+ goto end;
+
+state0_5:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'e') || (ch_ >= 'g' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_30;
+
+ if (ch_ == 'f') goto state0_31;
+ goto end;
+
+state0_6:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_32;
+ goto end;
+
+state0_7:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'g') || (ch_ >= 'i' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'h') goto state0_33;
+ goto end;
+
+state0_8:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_34;
+ goto end;
+
+state0_9:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '|') goto state0_35;
+ goto end;
+
+state0_10:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '&') goto state0_36;
+ goto end;
+
+state0_11:
+ end_state_ = true;
+ id_ = 61;
+ uid_ = 26;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_37;
+ goto end;
+
+state0_12:
+ end_state_ = true;
+ id_ = 262177;
+ uid_ = 20;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_38;
+ goto end;
+
+state0_13:
+ end_state_ = true;
+ id_ = 131091;
+ uid_ = 12;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_39;
+ goto end;
+
+state0_14:
+ end_state_ = true;
+ id_ = 131093;
+ uid_ = 14;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_40;
+ goto end;
+
+state0_15:
+ end_state_ = true;
+ id_ = 393241;
+ uid_ = 16;
+ end_token_ = curr_;
+ goto end;
+
+state0_16:
+ end_state_ = true;
+ id_ = 393242;
+ uid_ = 17;
+ end_token_ = curr_;
+ goto end;
+
+state0_17:
+ end_state_ = true;
+ id_ = 131099;
+ uid_ = 18;
+ end_token_ = curr_;
+ goto end;
+
+state0_18:
+ end_state_ = true;
+ id_ = 131100;
+ uid_ = 19;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_41;
+ goto end;
+
+state0_19:
+ end_state_ = true;
+ id_ = 40;
+ uid_ = 21;
+ end_token_ = curr_;
+ goto end;
+
+state0_20:
+ end_state_ = true;
+ id_ = 41;
+ uid_ = 22;
+ end_token_ = curr_;
+ goto end;
+
+state0_21:
+ end_state_ = true;
+ id_ = 123;
+ uid_ = 23;
+ end_token_ = curr_;
+ goto end;
+
+state0_22:
+ end_state_ = true;
+ id_ = 125;
+ uid_ = 24;
+ end_token_ = curr_;
+ goto end;
+
+state0_23:
+ end_state_ = true;
+ id_ = 44;
+ uid_ = 25;
+ end_token_ = curr_;
+ goto end;
+
+state0_24:
+ end_state_ = true;
+ id_ = 59;
+ uid_ = 27;
+ end_token_ = curr_;
+ goto end;
+
+state0_25:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_26:
+ end_state_ = true;
+ id_ = 34;
+ uid_ = 30;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_27:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_42;
+ goto end;
+
+state0_28:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_43;
+ goto end;
+
+state0_29:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_44;
+ goto end;
+
+state0_30:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_45;
+ goto end;
+
+state0_31:
+ end_state_ = true;
+ id_ = 65538;
+ uid_ = 4;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_32:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_46;
+ goto end;
+
+state0_33:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_47;
+ goto end;
+
+state0_34:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_48;
+ goto end;
+
+state0_35:
+ end_state_ = true;
+ id_ = 131084;
+ uid_ = 8;
+ end_token_ = curr_;
+ goto end;
+
+state0_36:
+ end_state_ = true;
+ id_ = 131085;
+ uid_ = 9;
+ end_token_ = curr_;
+ goto end;
+
+state0_37:
+ end_state_ = true;
+ id_ = 131089;
+ uid_ = 10;
+ end_token_ = curr_;
+ goto end;
+
+state0_38:
+ end_state_ = true;
+ id_ = 131090;
+ uid_ = 11;
+ end_token_ = curr_;
+ goto end;
+
+state0_39:
+ end_state_ = true;
+ id_ = 131092;
+ uid_ = 13;
+ end_token_ = curr_;
+ goto end;
+
+state0_40:
+ end_state_ = true;
+ id_ = 131094;
+ uid_ = 15;
+ end_token_ = curr_;
+ goto end;
+
+state0_41:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_41;
+
+ if (ch_ == '*') goto state0_49;
+ goto end;
+
+state0_42:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_50;
+ goto end;
+
+state0_43:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_42;
+ goto end;
+
+state0_44:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'c') || (ch_ >= 'e' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'd') goto state0_51;
+ goto end;
+
+state0_45:
+ end_state_ = true;
+ id_ = 65537;
+ uid_ = 3;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_46:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_52;
+ goto end;
+
+state0_47:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_53;
+ goto end;
+
+state0_48:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_54;
+ goto end;
+
+state0_49:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_49;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+ goto end;
+
+state0_50:
+ end_state_ = true;
+ id_ = 36;
+ uid_ = 1;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_51:
+ end_state_ = true;
+ id_ = 65536;
+ uid_ = 2;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_52:
+ end_state_ = true;
+ id_ = 65539;
+ uid_ = 5;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_53:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_57;
+ goto end;
+
+state0_54:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_58;
+ goto end;
+
+state0_55:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_55;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_56:
+ end_state_ = true;
+ id_ = 33;
+ uid_ = 29;
+ end_token_ = curr_;
+ goto end;
+
+state0_57:
+ end_state_ = true;
+ id_ = 65540;
+ uid_ = 6;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_58:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_60;
+ goto end;
+
+state0_59:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_60:
+ end_state_ = true;
+ id_ = 65541;
+ uid_ = 7;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+
+end:
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static_switch
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static_switch;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static_switch[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static_switch(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/error_handler.hpp
new file mode 100644
index 00000000..2b1ee5b2
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/error_handler.hpp
@@ -0,0 +1,105 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator, typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(BaseIterator first, BaseIterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ // retrieve underlying iterator from current token, err_pos points
+ // to the last validly matched token, so we use its end iterator
+ // as the error position
+ BaseIterator err_pos_base = err_pos->matched().end();
+ std::cout << message << what << std::endl;
+ if (err_pos_base != BaseIterator())
+ dump_error_line(err_pos_base);
+ }
+
+ void dump_error_line(BaseIterator err_pos_base) const
+ {
+ int line;
+ BaseIterator line_start = get_pos(err_pos_base, line);
+ if (err_pos_base != last)
+ {
+ std::cout << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos_base; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file.\n";
+ }
+
+ }
+
+ BaseIterator get_pos(BaseIterator err_pos, int& line) const
+ {
+ line = 1;
+ BaseIterator i = first;
+ BaseIterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(BaseIterator err_pos) const
+ {
+ BaseIterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ BaseIterator first;
+ BaseIterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.cpp
new file mode 100644
index 00000000..5b51ce36
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::expression<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.hpp
new file mode 100644
index 00000000..a5d431ef
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression.hpp
@@ -0,0 +1,58 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CONJURE_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct expression : qi::grammar<Iterator, ast::expression()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ expression(error_handler_type& error_handler, Lexer const& l);
+
+ Lexer const& lexer;
+
+ qi::rule<Iterator, ast::expression()> expr;
+ qi::rule<Iterator, ast::operand()> unary_expr, primary_expr;
+ qi::rule<Iterator, ast::function_call()> function_call;
+ qi::rule<Iterator, std::list<ast::expression>()> argument_list;
+ qi::rule<Iterator, std::string()> identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression_def.hpp
new file mode 100644
index 00000000..795051eb
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/expression_def.hpp
@@ -0,0 +1,94 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/lex_plain_token.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ expression<Iterator, Lexer>::expression(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : expression::base_type(expr), lexer(l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::tokenid_mask_type tokenid_mask;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ unary_expr
+ >> *(tokenid_mask(token_ids::op_binary) > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (tokenid_mask(token_ids::op_unary) > unary_expr)
+ ;
+
+ primary_expr =
+ lexer.lit_uint
+ | function_call
+ | identifier
+ | lexer.true_or_false
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier = lexer.identifier;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (unary_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.cpp
new file mode 100644
index 00000000..98c8169b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "function_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::function<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.hpp
new file mode 100644
index 00000000..fc5263f1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function.hpp
@@ -0,0 +1,36 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_FUNCTION_HPP)
+#define BOOST_SPIRIT_CONJURE_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct function : qi::grammar<Iterator, ast::function()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ function(error_handler_type& error_handler, Lexer const& l);
+
+ statement<Iterator, Lexer> body;
+
+ qi::rule<Iterator, ast::identifier()> identifier;
+ qi::rule<Iterator, std::list<ast::identifier>()> argument_list;
+ qi::rule<Iterator, ast::function()> start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function_def.hpp
new file mode 100644
index 00000000..72bab856
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/function_def.hpp
@@ -0,0 +1,64 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ function<Iterator, Lexer>::function(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : function::base_type(start), body(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ identifier = body.expr.identifier;
+ argument_list = -(identifier % ',');
+
+ start = (l.token("void") | l.token("int"))
+ > identifier
+ > '(' > argument_list > ')'
+ > '{' > body > '}'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ids.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ids.hpp
new file mode 100644
index 00000000..9446074c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/ids.hpp
@@ -0,0 +1,154 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_IDS_HPP)
+#define BOOST_SPIRIT_CONJURE_IDS_HPP
+
+namespace client
+{
+ struct op_type
+ {
+ enum type
+ {
+ binary = 0x20000,
+ unary = 0x40000,
+ assign = 0x80000
+ };
+ };
+
+ struct op
+ {
+ enum type
+ {
+ // binary
+ comma,
+ assign,
+ plus_assign,
+ minus_assign,
+ times_assign,
+ divide_assign,
+ mod_assign,
+ bit_and_assign,
+ bit_xor_assign,
+ bit_or_assign,
+ shift_left_assign,
+ shift_right_assign,
+ logical_or,
+ logical_and,
+ bit_or,
+ bit_xor,
+ bit_and,
+ equal,
+ not_equal,
+ less,
+ less_equal,
+ greater,
+ greater_equal,
+ shift_left,
+ shift_right,
+ plus,
+ minus,
+ times,
+ divide,
+ mod,
+
+ // unary
+ plus_plus,
+ minus_minus,
+ compl_,
+ not_,
+ };
+ };
+
+ template <int type, int op>
+ struct make_op
+ {
+ static int const value = type + op;
+ };
+
+ template <op::type op>
+ struct unary_op : make_op<op_type::unary, op> {};
+
+ template <op::type op>
+ struct binary_op
+ : make_op<op_type::binary, op> {};
+
+ template <op::type op>
+ struct assign_op
+ : make_op<op_type::assign, op> {};
+
+ template <op::type op>
+ struct binary_or_unary_op
+ : make_op<op_type::unary | op_type::binary, op> {};
+
+ struct token_ids
+ {
+ enum type
+ {
+ // pseudo tags
+ invalid = -1,
+ op_binary = op_type::binary,
+ op_unary = op_type::unary,
+ op_assign = op_type::assign,
+
+ // binary / unary operators with common tokens
+ // '+' and '-' can be binary or unary
+ // (the lexer cannot distinguish which)
+ plus = binary_or_unary_op<op::plus>::value,
+ minus = binary_or_unary_op<op::minus>::value,
+
+ // binary operators
+ comma = binary_op<op::comma>::value,
+ assign = assign_op<op::assign>::value,
+ plus_assign = assign_op<op::plus_assign>::value,
+ minus_assign = assign_op<op::minus_assign>::value,
+ times_assign = assign_op<op::times_assign>::value,
+ divide_assign = assign_op<op::divide_assign>::value,
+ mod_assign = assign_op<op::mod_assign>::value,
+ bit_and_assign = assign_op<op::bit_and_assign>::value,
+ bit_xor_assign = assign_op<op::bit_xor_assign>::value,
+ bit_or_assign = assign_op<op::bit_or_assign>::value,
+ shift_left_assign = assign_op<op::shift_left_assign>::value,
+ shift_right_assign = assign_op<op::shift_right_assign>::value,
+ logical_or = binary_op<op::logical_or>::value,
+ logical_and = binary_op<op::logical_and>::value,
+ bit_or = binary_op<op::bit_or>::value,
+ bit_xor = binary_op<op::bit_xor>::value,
+ bit_and = binary_op<op::bit_and>::value,
+ equal = binary_op<op::equal>::value,
+ not_equal = binary_op<op::not_equal>::value,
+ less = binary_op<op::less>::value,
+ less_equal = binary_op<op::less_equal>::value,
+ greater = binary_op<op::greater>::value,
+ greater_equal = binary_op<op::greater_equal>::value,
+ shift_left = binary_op<op::shift_left>::value,
+ shift_right = binary_op<op::shift_right>::value,
+ times = binary_op<op::times>::value,
+ divide = binary_op<op::divide>::value,
+ mod = binary_op<op::mod>::value,
+
+ // unary operators with overlaps
+ // '++' and '--' can be prefix or postfix
+ // (the lexer cannot distinguish which)
+ plus_plus = unary_op<op::plus_plus>::value,
+ minus_minus = unary_op<op::minus_minus>::value,
+
+ // unary operators
+ compl_ = unary_op<op::compl_>::value,
+ not_ = unary_op<op::not_>::value,
+
+ // misc tags
+ identifier = op::not_ + 1,
+ comment,
+ whitespace,
+ lit_uint,
+ true_or_false
+ };
+ };
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.cpp
new file mode 100644
index 00000000..7ce7ec0c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.cpp
@@ -0,0 +1,17 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+template client::lexer::conjure_tokens<base_iterator_type>::conjure_tokens();
+template bool client::lexer::conjure_tokens<base_iterator_type>::add_keyword(
+ std::string const&);
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.hpp
new file mode 100644
index 00000000..c4945779
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer.hpp
@@ -0,0 +1,128 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_HPP
+
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/lex_lexertl_position_token.hpp>
+
+#include "config.hpp"
+#include "ids.hpp"
+
+#if CONJURE_LEXER_STATIC_TABLES != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_lexer.hpp"
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_switch_lexer.hpp"
+#endif
+#include <boost/assert.hpp>
+
+namespace client { namespace lexer
+{
+ namespace lex = boost::spirit::lex;
+
+ ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ namespace lex = boost::spirit::lex;
+
+ template <typename BaseIterator>
+ struct get_lexer_type
+ {
+ // Our token needs to be able to carry several token values:
+ // std::string, unsigned int, and bool
+ typedef boost::mpl::vector<std::string, unsigned int, bool>
+ token_value_types;
+
+ // Using the position_token class as the token type to be returned
+ // from the lexer iterators allows to retain positional information
+ // as every token instance stores an iterator pair pointing to the
+ // matched input sequence.
+ typedef lex::lexertl::position_token<
+ BaseIterator, token_value_types, boost::mpl::false_
+ > token_type;
+
+#if CONJURE_LEXER_DYNAMIC_TABLES != 0
+ // use the lexer based on runtime generated DFA tables
+ typedef lex::lexertl::actor_lexer<token_type> type;
+#elif CONJURE_LEXER_STATIC_TABLES != 0
+ // use the lexer based on pre-generated static DFA tables
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static
+ > type;
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+ // use the lexer based on pre-generated static code
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static_switch
+ > type;
+#else
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator>
+ struct conjure_tokens
+ : lex::lexer<typename detail::get_lexer_type<BaseIterator>::type>
+ {
+ private:
+ // get the type of any qi::raw_token(...) and qi::token(...) constructs
+ typedef typename boost::spirit::result_of::terminal<
+ boost::spirit::tag::raw_token(token_ids::type)
+ >::type raw_token_spec;
+
+ typedef typename boost::spirit::result_of::terminal<
+ boost::spirit::tag::token(token_ids::type)
+ >::type token_spec;
+
+ typedef std::map<std::string, token_ids::type> keyword_map_type;
+
+ protected:
+ // add a keyword to the mapping table
+ bool add_keyword(std::string const& keyword);
+
+ public:
+ typedef BaseIterator base_iterator_type;
+
+ conjure_tokens();
+
+ // extract a raw_token(id) for the given registered keyword
+ raw_token_spec operator()(std::string const& kwd) const
+ {
+ namespace qi = boost::spirit::qi;
+ qi::raw_token_type raw_token;
+
+ typename keyword_map_type::const_iterator it = keywords_.find(kwd);
+ BOOST_ASSERT(it != keywords_.end());
+ return raw_token((it != keywords_.end()) ? (*it).second : token_ids::invalid);
+ }
+
+ // extract a token(id) for the given registered keyword
+ token_spec token(std::string const& kwd) const
+ {
+ namespace qi = boost::spirit::qi;
+ qi::token_type token;
+
+ typename keyword_map_type::const_iterator it = keywords_.find(kwd);
+ BOOST_ASSERT(it != keywords_.end());
+ return token((it != keywords_.end()) ? (*it).second : token_ids::invalid);
+ }
+
+ lex::token_def<std::string> identifier;
+ lex::token_def<unsigned int> lit_uint;
+ lex::token_def<bool> true_or_false;
+ keyword_map_type keywords_;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer_def.hpp
new file mode 100644
index 00000000..cab990f7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/lexer_def.hpp
@@ -0,0 +1,74 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "lexer.hpp"
+
+namespace client { namespace lexer
+{
+ template <typename BaseIterator>
+ conjure_tokens<BaseIterator>::conjure_tokens()
+ : identifier("[a-zA-Z_][a-zA-Z_0-9]*", token_ids::identifier)
+ , lit_uint("[0-9]+", token_ids::lit_uint)
+ , true_or_false("true|false", token_ids::true_or_false)
+ {
+ lex::_pass_type _pass;
+
+ this->self = lit_uint | true_or_false;
+
+ add_keyword("void");
+ add_keyword("int");
+ add_keyword("if");
+ add_keyword("else");
+ add_keyword("while");
+ add_keyword("return");
+
+ this->self.add
+ ("\\|\\|", token_ids::logical_or)
+ ("&&", token_ids::logical_and)
+ ("==", token_ids::equal)
+ ("!=", token_ids::not_equal)
+ ("<", token_ids::less)
+ ("<=", token_ids::less_equal)
+ (">", token_ids::greater)
+ (">=", token_ids::greater_equal)
+ ("\\+", token_ids::plus)
+ ("\\-", token_ids::minus)
+ ("\\*", token_ids::times)
+ ("\\/", token_ids::divide)
+ ("!", token_ids::not_)
+ ;
+
+ this->self += lex::char_('(') | ')' | '{' | '}' | ',' | '=' | ';';
+
+ this->self +=
+ identifier
+ | lex::string("\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/", token_ids::comment)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ | lex::string("[ \t\n\r]+", token_ids::whitespace)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ ;
+ }
+
+ template <typename BaseIterator>
+ bool conjure_tokens<BaseIterator>::add_keyword(std::string const& keyword)
+ {
+ // add the token to the lexer
+ token_ids::type id = token_ids::type(this->get_next_id());
+ this->self.add(keyword, id);
+
+ // store the mapping for later retrieval
+ std::pair<typename keyword_map_type::iterator, bool> p =
+ keywords_.insert(typename keyword_map_type::value_type(keyword, id));
+
+ return p.second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/main.cpp
new file mode 100644
index 00000000..3e4e83c9
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/main.cpp
@@ -0,0 +1,131 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ HK June 3, 2011 ] Adding lexer
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "config.hpp"
+#include "function.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include "lexer.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+ typedef lexer_type::iterator_type iterator_type;
+
+ lexer_type lexer; // Our lexer
+
+ base_iterator_type first = source_code.begin();
+ base_iterator_type last = source_code.end();
+
+ iterator_type iter = lexer.begin(first, last);
+ iterator_type end = lexer.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<base_iterator_type, iterator_type>
+ error_handler(first, last); // Our error handler
+ client::parser::function<iterator_type, lexer_type>
+ function(error_handler, lexer); // Our parser
+ client::code_gen::compiler
+ compiler(error_handler); // Our compiler
+
+ // note: we don't need a skipper
+ bool success = parse(iter, end, +function, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ boost::shared_ptr<client::code_gen::function>
+ p = compiler.find_function("main");
+ if (!p)
+ return 1;
+
+ int nargs = argc-2;
+ if (p->nargs() != nargs)
+ {
+ std::cerr << "Error: main function requires " << p->nargs() << " arguments." << std::endl;
+ std::cerr << nargs << " supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ compiler.print_assembler();
+
+ // Push the arguments into our stack
+ for (int i = 0; i < nargs; ++i)
+ vm.get_stack()[i] = boost::lexical_cast<int>(argv[i+2]);
+
+ // Call the interpreter
+ int r = vm.execute(compiler.get_code());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ error_handler.dump_error_line(first);
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.cpp
new file mode 100644
index 00000000..ca85a61c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::statement<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.hpp
new file mode 100644
index 00000000..208ca247
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement.hpp
@@ -0,0 +1,42 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_STATEMENT_HPP)
+#define BOOST_SPIRIT_CONJURE_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct statement : qi::grammar<Iterator, ast::statement_list()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ statement(error_handler_type& error_handler, Lexer const& l);
+
+ expression<Iterator, Lexer> expr;
+
+ qi::rule<Iterator, ast::statement_list()>
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement()> statement_;
+ qi::rule<Iterator, ast::variable_declaration()> variable_declaration;
+ qi::rule<Iterator, ast::assignment()> assignment;
+ qi::rule<Iterator, ast::if_statement()> if_statement;
+ qi::rule<Iterator, ast::while_statement()> while_statement;
+ qi::rule<Iterator, ast::return_statement()> return_statement;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement_def.hpp
new file mode 100644
index 00000000..ab937085
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/statement_def.hpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ statement<Iterator, Lexer>::statement(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : statement::base_type(statement_list), expr(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ ;
+
+ variable_declaration =
+ l("int")
+ > expr.identifier
+ > -('=' > expr)
+ > ';'
+ ;
+
+ assignment =
+ expr.identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ l("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ l("else")
+ > statement_
+ )
+ ;
+
+ while_statement =
+ l("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ l("return")
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (statement_)
+ (variable_declaration)
+ (assignment)
+ (if_statement)
+ (while_statement)
+ (compound_statement)
+ (return_statement)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in variable_declaration,
+ // assignment and return_statement, call annotation.
+ on_success(variable_declaration,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.cpp
new file mode 100644
index 00000000..af68f523
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.cpp
@@ -0,0 +1,160 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "config.hpp"
+#include "vm.hpp"
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (true)
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr += *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.hpp
new file mode 100644
index 00000000..0362eaf8
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure2/vm.hpp
@@ -0,0 +1,82 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_VM_HPP)
+#define BOOST_SPIRIT_CONJURE_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ }
+
+ std::vector<int> const& get_stack() const { return stack; };
+ std::vector<int>& get_stack() { return stack; };
+
+ private:
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp
new file mode 100644
index 00000000..3b876431
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp
@@ -0,0 +1,141 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CONJURE_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ struct set_annotation_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_annotation_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ template <typename T>
+ void dispatch(T& x, boost::mpl::true_) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void dispatch(T& x, boost::mpl::false_) const
+ {
+ // no-op
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ typename boost::is_base_of<ast::tagged, T> is_tagged;
+ dispatch(x, is_tagged);
+ }
+ };
+
+ struct get_annotation_id
+ {
+ typedef int result_type;
+
+ int operator()(ast::function_call& x) const
+ {
+ return x.function_name.id;
+ }
+
+ template <typename T>
+ int dispatch(T& x, boost::mpl::true_) const
+ {
+ return x.id;
+ }
+
+ template <typename T>
+ int dispatch(T& x, boost::mpl::false_) const
+ {
+ return -1;
+ }
+
+ template <typename T>
+ int operator()(T& x) const
+ {
+ typename boost::is_base_of<ast::tagged, T> is_tagged;
+ return dispatch(x, is_tagged);
+ }
+ };
+
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_annotation_id(id), ast);
+ ast.id = id;
+ }
+
+ void operator()(ast::primary_expr& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_annotation_id(id), ast);
+ ast.id = id;
+ }
+
+ void operator()(ast::variable_declaration& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp
new file mode 100644
index 00000000..a77cb0ed
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp
@@ -0,0 +1,240 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_AST_HPP)
+#define BOOST_SPIRIT_CONJURE_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/spirit/include/support_extended_variant.hpp>
+#include <boost/spirit/include/support_attributes.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+#include "ids.hpp"
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary_expr;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ struct primary_expr :
+ tagged,
+ boost::spirit::extended_variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<expression>
+ >
+ {
+ primary_expr() : base_type() {}
+ primary_expr(bool val) : base_type(val) {}
+ primary_expr(unsigned int val) : base_type(val) {}
+ primary_expr(identifier const& val) : base_type(val) {}
+ primary_expr(expression const& val) : base_type(val) {}
+ primary_expr(primary_expr const& rhs)
+ : base_type(rhs.get()) {}
+ };
+
+ struct operand :
+ tagged,
+ boost::spirit::extended_variant<
+ nil
+ , primary_expr
+ , boost::recursive_wrapper<unary_expr>
+ , boost::recursive_wrapper<function_call>
+ >
+ {
+ operand() : base_type() {}
+ operand(primary_expr const& val) : base_type(val) {}
+ operand(unary_expr const& val) : base_type(val) {}
+ operand(function_call const& val) : base_type(val) {}
+ operand(operand const& rhs)
+ : base_type(rhs.get()) {}
+ };
+
+ struct unary_expr : tagged
+ {
+ token_ids::type operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ token_ids::type operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ token_ids::type operator_;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ nil
+ , variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ , boost::recursive_wrapper<expression>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ boost::optional<statement_list> body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary_expr,
+ (client::token_ids::type, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::token_ids::type, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::token_ids::type, operator_)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (boost::optional<client::ast::statement_list>, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp
new file mode 100644
index 00000000..e36ad770
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp
@@ -0,0 +1,1141 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "config.hpp"
+#include "compiler.hpp"
+#include "annotation.hpp"
+#include "vm.hpp"
+
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/range/adaptor/transformed.hpp>
+#include <boost/assert.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ value::value()
+ : v(0),
+ is_lvalue_(false),
+ builder(0)
+ {}
+
+ value::value(
+ llvm::Value* v,
+ bool is_lvalue_,
+ llvm::IRBuilder<>* builder)
+ : v(v),
+ is_lvalue_(is_lvalue_),
+ builder(builder)
+ {}
+
+ value::value(value const& rhs)
+ : v(rhs.v),
+ is_lvalue_(rhs.is_lvalue_),
+ builder(rhs.builder)
+ {}
+
+ bool value::is_lvalue() const
+ {
+ return is_lvalue_;
+ }
+
+ bool value::is_valid() const
+ {
+ return v != 0;
+ }
+
+ value::operator bool() const
+ {
+ return v != 0;
+ }
+
+ void value::name(char const* id)
+ {
+ v->setName(id);
+ }
+
+ void value::name(std::string const& id)
+ {
+ v->setName(id);
+ }
+
+ value::operator llvm::Value*() const
+ {
+ if (is_lvalue_)
+ {
+ BOOST_ASSERT(builder != 0);
+ return builder->CreateLoad(v, v->getName());
+ }
+ return v;
+ }
+
+ value& value::operator=(value const& rhs)
+ {
+ v = rhs.v;
+ is_lvalue_ = rhs.is_lvalue_;
+ builder = rhs.builder;
+ return *this;
+ }
+
+ value& value::assign(value const& rhs)
+ {
+ BOOST_ASSERT(is_lvalue());
+ BOOST_ASSERT(builder != 0);
+ builder->CreateStore(rhs, v);
+ return *this;
+ }
+
+ value operator-(value a)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateNeg(a, "neg_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator!(value a)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateNot(a, "not_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator+(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateAdd(a, b, "add_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator-(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateSub(a, b, "sub_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator*(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateMul(a, b, "mul_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator/(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateSDiv(a, b, "div_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator%(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateSRem(a, b, "mod_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator&(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateAnd(a, b, "and_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator|(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateOr(a, b, "or_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator^(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateXor(a, b, "xor_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator<<(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateShl(a, b, "shl_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator>>(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateLShr(a, b, "shr_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator==(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpEQ(a, b, "eq_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator!=(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpNE(a, b, "ne_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator<(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpSLT(a, b, "slt_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator<=(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpSLE(a, b, "sle_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator>(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpSGT(a, b, "sgt_tmp"),
+ false, a.builder
+ );
+ }
+
+ value operator>=(value a, value b)
+ {
+ BOOST_ASSERT(a.builder != 0);
+ return value(
+ a.builder->CreateICmpSGE(a, b, "sge_tmp"),
+ false, a.builder
+ );
+ }
+
+ struct function::to_value
+ {
+ typedef value result_type;
+ llvm_compiler* c;
+
+ to_value(llvm_compiler* c = 0) : c(c) {}
+
+ value operator()(llvm::Value& v) const
+ {
+ return c->val(&v);
+ }
+ };
+
+ bool basic_block::has_terminator() const
+ {
+ return b->getTerminator() != 0;
+ }
+
+ bool basic_block::is_valid() const
+ {
+ return b != 0;
+ }
+
+ function::operator llvm::Function*() const
+ {
+ return f;
+ }
+
+ std::size_t function::arg_size() const
+ {
+ return f->arg_size();
+ }
+
+ void function::add(basic_block const& b)
+ {
+ f->getBasicBlockList().push_back(b);
+ }
+
+ void function::erase_from_parent()
+ {
+ f->eraseFromParent();
+ }
+
+ basic_block function::last_block()
+ {
+ return &f->getBasicBlockList().back();
+ }
+
+ bool function::empty() const
+ {
+ return f->empty();
+ }
+
+ std::string function::name() const
+ {
+ return f->getName();
+ }
+
+ function::arg_range function::args() const
+ {
+ BOOST_ASSERT(c != 0);
+ arg_val_iterator first(f->arg_begin(), to_value());
+ arg_val_iterator last(f->arg_end(), to_value());
+ return arg_range(first, last);
+ }
+
+ bool function::is_valid() const
+ {
+ return f != 0;
+ }
+
+ void function::verify() const
+ {
+ llvm::verifyFunction(*f);
+ }
+
+ value llvm_compiler::val(unsigned int x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(int x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(int_size, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(bool x)
+ {
+ return value(
+ llvm::ConstantInt::get(context(), llvm::APInt(1, x)),
+ false, &llvm_builder);
+ }
+
+ value llvm_compiler::val(llvm::Value* v)
+ {
+ return value(v, false, &llvm_builder);
+ }
+
+ namespace
+ {
+ // Create an alloca instruction in the entry block of
+ // the function. This is used for mutable variables etc.
+ llvm::AllocaInst*
+ make_entry_block_alloca(
+ llvm::Function* f,
+ char const* name,
+ llvm::LLVMContext& context)
+ {
+ llvm::IRBuilder<> builder(
+ &f->getEntryBlock(),
+ f->getEntryBlock().begin());
+
+ return builder.CreateAlloca(
+ llvm::Type::getIntNTy(context, int_size), 0, name);
+ }
+ }
+
+ value llvm_compiler::var(char const* name)
+ {
+ llvm::Function* f = llvm_builder.GetInsertBlock()->getParent();
+ llvm::IRBuilder<> builder(
+ &f->getEntryBlock(),
+ f->getEntryBlock().begin());
+
+ llvm::AllocaInst* alloca = builder.CreateAlloca(
+ llvm::Type::getIntNTy(context(), int_size), 0, name);
+
+ return value(alloca, true, &llvm_builder);
+ }
+
+ struct value::to_llvm_value
+ {
+ typedef llvm::Value* result_type;
+ llvm::Value* operator()(value const& x) const
+ {
+ return x;
+ }
+ };
+
+ template <typename C>
+ llvm::Value* llvm_compiler::call_impl(
+ function callee,
+ C const& args_)
+ {
+ // Sigh. LLVM requires CreateCall arguments to be random access.
+ // It would have been better if it can accept forward iterators.
+ // I guess it needs the arguments to be in contiguous memory.
+ // So, we have to put the args into a temporary std::vector.
+ std::vector<llvm::Value*> args(
+ args_.begin(), args_.end());
+
+ // Check the args for null values. We can't have null values.
+ // Return 0 if we find one to flag error.
+ BOOST_FOREACH(llvm::Value* arg, args)
+ {
+ if (arg == 0)
+ return 0;
+ }
+
+ return llvm_builder.CreateCall(
+ callee, args.begin(), args.end(), "call_tmp");
+ }
+
+ template <typename Container>
+ value llvm_compiler::call(
+ function callee,
+ Container const& args)
+ {
+ llvm::Value* call = call_impl(
+ callee,
+ args | boost::adaptors::transformed(value::to_llvm_value()));
+
+ if (call == 0)
+ return val();
+ return value(call, false, &llvm_builder);
+ }
+
+ function llvm_compiler::get_function(char const* name)
+ {
+ return function(vm.module()->getFunction(name), this);
+ }
+
+ function llvm_compiler::get_current_function()
+ {
+ // get the current function
+ return function(llvm_builder.GetInsertBlock()->getParent(), this);
+ }
+
+ function llvm_compiler::declare_function(
+ bool void_return
+ , std::string const& name
+ , std::size_t nargs)
+ {
+ llvm::Type const* int_type =
+ llvm::Type::getIntNTy(context(), int_size);
+ llvm::Type const* void_type = llvm::Type::getVoidTy(context());
+
+ std::vector<llvm::Type const*> ints(nargs, int_type);
+ llvm::Type const* return_type = void_return ? void_type : int_type;
+
+ llvm::FunctionType* function_type =
+ llvm::FunctionType::get(void_return ? void_type : int_type, ints, false);
+
+ return function(llvm::Function::Create(
+ function_type, llvm::Function::ExternalLinkage,
+ name, vm.module()), this);
+ }
+
+ basic_block llvm_compiler::make_basic_block(
+ char const* name
+ , function parent
+ , basic_block before)
+ {
+ return llvm::BasicBlock::Create(context(), name, parent, before);
+ }
+
+ value llvm_compiler::var(std::string const& name)
+ {
+ return var(name.c_str());
+ }
+
+ function llvm_compiler::get_function(std::string const& name)
+ {
+ return get_function(name.c_str());
+ }
+
+ basic_block llvm_compiler::get_insert_block()
+ {
+ return llvm_builder.GetInsertBlock();
+ }
+
+ void llvm_compiler::set_insert_point(basic_block b)
+ {
+ llvm_builder.SetInsertPoint(b);
+ }
+
+ void llvm_compiler::conditional_branch(
+ value cond, basic_block true_br, basic_block false_br)
+ {
+ llvm_builder.CreateCondBr(cond, true_br, false_br);
+ }
+
+ void llvm_compiler::branch(basic_block b)
+ {
+ llvm_builder.CreateBr(b);
+ }
+
+ void llvm_compiler::return_()
+ {
+ llvm_builder.CreateRetVoid();
+ }
+
+ void llvm_compiler::return_(value v)
+ {
+ llvm_builder.CreateRet(v);
+ }
+
+ void llvm_compiler::optimize_function(function f)
+ {
+ // Optimize the function.
+ fpm.run(*f);
+ }
+
+ void llvm_compiler::init_fpm()
+ {
+ // Set up the optimizer pipeline. Start with registering info about how the
+ // target lays out data structures.
+ fpm.add(new llvm::TargetData(*vm.execution_engine()->getTargetData()));
+ // Provide basic AliasAnalysis support for GVN.
+ fpm.add(llvm::createBasicAliasAnalysisPass());
+ // Promote allocas to registers.
+ fpm.add(llvm::createPromoteMemoryToRegisterPass());
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ fpm.add(llvm::createInstructionCombiningPass());
+ // Reassociate expressions.
+ fpm.add(llvm::createReassociatePass());
+ // Eliminate Common SubExpressions.
+ fpm.add(llvm::createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ fpm.add(llvm::createCFGSimplificationPass());
+
+ fpm.doInitialization();
+ }
+
+ value compiler::operator()(unsigned int x)
+ {
+ return val(x);
+ }
+
+ value compiler::operator()(bool x)
+ {
+ return val(x);
+ }
+
+ value compiler::operator()(ast::primary_expr const& x)
+ {
+ return boost::apply_visitor(*this, x.get());
+ }
+
+ value compiler::operator()(ast::identifier const& x)
+ {
+ // Look this variable up in the function.
+ if (locals.find(x.name) == locals.end())
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return val();
+ }
+ return locals[x.name];
+ }
+
+ value compiler::operator()(ast::unary_expr const& x)
+ {
+ value operand = boost::apply_visitor(*this, x.operand_);
+ if (!operand.is_valid())
+ return val();
+
+ switch (x.operator_)
+ {
+ case token_ids::compl_: return operand ^ val(-1);
+ case token_ids::minus: return -operand;
+ case token_ids::not_: return !operand;
+ case token_ids::plus: return operand;
+ case token_ids::plus_plus:
+ {
+ if (!operand.is_lvalue())
+ {
+ error_handler(x.id, "++ needs an var");
+ return val();
+ }
+
+ value r = operand + val(1);
+ operand.assign(r);
+ return operand;
+ }
+ case token_ids::minus_minus:
+ {
+ if (!operand.is_lvalue())
+ {
+ error_handler(x.id, "-- needs an var");
+ return val();
+ }
+
+ value r = operand - val(1);
+ operand.assign(r);
+ return operand;
+ }
+ default:
+ BOOST_ASSERT(0);
+ return val();
+ }
+ }
+
+ namespace
+ {
+ struct compile_args
+ {
+ compiler& c;
+ compile_args(compiler& c) : c(c) {}
+
+ typedef value result_type;
+ value operator()(ast::expression const& expr) const
+ {
+ return c(expr);
+ }
+ };
+ }
+
+ value compiler::operator()(ast::function_call const& x)
+ {
+ function callee = get_function(x.function_name.name);
+ if (!callee.is_valid())
+ {
+ error_handler(x.function_name.id,
+ "Function not found: " + x.function_name.name);
+ return val();
+ }
+
+ if (callee.arg_size() != x.args.size())
+ {
+ error_handler(x.function_name.id,
+ "Wrong number of arguments: " + x.function_name.name);
+ return val();
+ }
+
+ return call(callee,
+ x.args | boost::adaptors::transformed(compile_args(*this)));
+ }
+
+ namespace
+ {
+ int precedence[] = {
+ // precedence 1
+ 1, // op_comma
+
+ // precedence 2
+ 2, // op_assign
+ 2, // op_plus_assign
+ 2, // op_minus_assign
+ 2, // op_times_assign
+ 2, // op_divide_assign
+ 2, // op_mod_assign
+ 2, // op_bit_and_assign
+ 2, // op_bit_xor_assign
+ 2, // op_bitor_assign
+ 2, // op_shift_left_assign
+ 2, // op_shift_right_assign
+
+ // precedence 3
+ 3, // op_logical_or
+
+ // precedence 4
+ 4, // op_logical_and
+
+ // precedence 5
+ 5, // op_bit_or
+
+ // precedence 6
+ 6, // op_bit_xor
+
+ // precedence 7
+ 7, // op_bit_and
+
+ // precedence 8
+ 8, // op_equal
+ 8, // op_not_equal
+
+ // precedence 9
+ 9, // op_less
+ 9, // op_less_equal
+ 9, // op_greater
+ 9, // op_greater_equal
+
+ // precedence 10
+ 10, // op_shift_left
+ 10, // op_shift_right
+
+ // precedence 11
+ 11, // op_plus
+ 11, // op_minus
+
+ // precedence 12
+ 12, // op_times
+ 12, // op_divide
+ 12 // op_mod
+ };
+ }
+
+ inline int precedence_of(token_ids::type op)
+ {
+ return precedence[op & 0xFF];
+ }
+
+ value compiler::compile_binary_expression(
+ value lhs, value rhs, token_ids::type op)
+ {
+ switch (op)
+ {
+ case token_ids::plus: return lhs + rhs;
+ case token_ids::minus: return lhs - rhs;
+ case token_ids::times: return lhs * rhs;
+ case token_ids::divide: return lhs / rhs;
+ case token_ids::mod: return lhs % rhs;
+
+ case token_ids::logical_or:
+ case token_ids::bit_or: return lhs | rhs;
+
+ case token_ids::logical_and:
+ case token_ids::bit_and: return lhs & rhs;
+
+ case token_ids::bit_xor: return lhs ^ rhs;
+ case token_ids::shift_left: return lhs << rhs;
+ case token_ids::shift_right: return lhs >> rhs;
+
+ case token_ids::equal: return lhs == rhs;
+ case token_ids::not_equal: return lhs != rhs;
+ case token_ids::less: return lhs < rhs;
+ case token_ids::less_equal: return lhs <= rhs;
+ case token_ids::greater: return lhs > rhs;
+ case token_ids::greater_equal: return lhs >= rhs;
+
+ default: BOOST_ASSERT(0); return val();
+ }
+ }
+
+ // The Shunting-yard algorithm
+ value compiler::compile_expression(
+ int min_precedence,
+ value lhs,
+ std::list<ast::operation>::const_iterator& rest_begin,
+ std::list<ast::operation>::const_iterator rest_end)
+ {
+ while ((rest_begin != rest_end) &&
+ (precedence_of(rest_begin->operator_) >= min_precedence))
+ {
+ token_ids::type op = rest_begin->operator_;
+ value rhs = boost::apply_visitor(*this, rest_begin->operand_);
+ if (!rhs.is_valid())
+ return val();
+ ++rest_begin;
+
+ while ((rest_begin != rest_end) &&
+ (precedence_of(rest_begin->operator_) > precedence_of(op)))
+ {
+ token_ids::type next_op = rest_begin->operator_;
+ rhs = compile_expression(
+ precedence_of(next_op), rhs, rest_begin, rest_end);
+ }
+
+ lhs = compile_binary_expression(lhs, rhs, op);
+ }
+ return lhs;
+ }
+
+ value compiler::operator()(ast::expression const& x)
+ {
+ value lhs = boost::apply_visitor(*this, x.first);
+ if (!lhs.is_valid())
+ return val();
+ std::list<ast::operation>::const_iterator rest_begin = x.rest.begin();
+ return compile_expression(0, lhs, rest_begin, x.rest.end());
+ }
+
+ value compiler::operator()(ast::assignment const& x)
+ {
+ if (locals.find(x.lhs.name) == locals.end())
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return val();
+ }
+
+ value lhs = locals[x.lhs.name];
+ value rhs = (*this)(x.rhs);
+ if (!rhs.is_valid())
+ return val();
+
+ if (x.operator_ == token_ids::assign)
+ {
+ lhs.assign(rhs);
+ return lhs;
+ }
+
+ value result;
+ switch (x.operator_)
+ {
+ case token_ids::plus_assign: result = lhs + rhs; break;
+ case token_ids::minus_assign: result = lhs - rhs; break;
+ case token_ids::times_assign: result = lhs * rhs; break;
+ case token_ids::divide_assign: result = lhs / rhs; break;
+ case token_ids::mod_assign: result = lhs % rhs; break;
+ case token_ids::bit_and_assign: result = lhs & rhs; break;
+ case token_ids::bit_xor_assign: result = lhs ^ rhs; break;
+ case token_ids::bit_or_assign: result = lhs | rhs; break;
+ case token_ids::shift_left_assign: result = lhs << rhs; break;
+ case token_ids::shift_right_assign: result = lhs >> rhs; break;
+ default: BOOST_ASSERT(0); return val();
+ }
+
+ lhs.assign(result);
+ return lhs;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ if (locals.find(x.lhs.name) != locals.end())
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+
+ value init;
+ std::string const& name = x.lhs.name;
+
+ if (x.rhs) // if there's an RHS initializer
+ {
+ init = (*this)(*x.rhs);
+ if (!init.is_valid()) // don't add the variable if the RHS fails
+ return false;
+ }
+
+ value var_ = var(name.c_str());
+ if (init.is_valid())
+ var_.assign(init);
+
+ // Remember this binding.
+ locals[name] = var_;
+ return true;
+ }
+
+ struct compiler::statement_compiler : compiler
+ {
+ typedef bool result_type;
+ };
+
+ compiler::statement_compiler& compiler::as_statement()
+ {
+ return *static_cast<statement_compiler*>(this);
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ if (boost::get<ast::nil>(&x) != 0) // empty statement
+ return true;
+ return boost::apply_visitor(as_statement(), x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ value condition = (*this)(x.condition);
+ if (!condition.is_valid())
+ return false;
+
+ function f = get_current_function();
+
+ // Create blocks for the then and else cases. Insert the 'then' block at the
+ // end of the function.
+ basic_block then_block = make_basic_block("if.then", f);
+ basic_block else_block;
+ basic_block exit_block;
+
+ if (x.else_)
+ {
+ else_block = make_basic_block("if.else");
+ conditional_branch(condition, then_block, else_block);
+ }
+ else
+ {
+ exit_block = make_basic_block("if.end");
+ conditional_branch(condition, then_block, exit_block);
+ }
+
+ // Emit then value.
+ set_insert_point(then_block);
+ if (!(*this)(x.then))
+ return false;
+ if (!then_block.has_terminator())
+ {
+ if (!exit_block.is_valid())
+ exit_block = make_basic_block("if.end");
+ branch(exit_block);
+ }
+ // Codegen of 'then' can change the current block, update then_block
+ then_block = get_insert_block();
+
+ if (x.else_)
+ {
+ // Emit else block.
+ f.add(else_block);
+ set_insert_point(else_block);
+ if (!(*this)(*x.else_))
+ return false;
+ if (!else_block.has_terminator())
+ {
+ if (!exit_block.is_valid())
+ exit_block = make_basic_block("if.end");
+ branch(exit_block);
+ }
+ // Codegen of 'else' can change the current block, update else_block
+ else_block = get_insert_block();
+ }
+
+ if (exit_block.is_valid())
+ {
+ // Emit exit block
+ f.add(exit_block);
+ set_insert_point(exit_block);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ function f = get_current_function();
+
+ basic_block cond_block = make_basic_block("while.cond", f);
+ basic_block body_block = make_basic_block("while.body");
+ basic_block exit_block = make_basic_block("while.end");
+
+ branch(cond_block);
+ set_insert_point(cond_block);
+ value condition = (*this)(x.condition);
+ if (!condition.is_valid())
+ return false;
+ conditional_branch(condition, body_block, exit_block);
+ f.add(body_block);
+ set_insert_point(body_block);
+
+ if (!(*this)(x.body))
+ return false;
+
+ if (!body_block.has_terminator())
+ branch(cond_block); // loop back
+
+ // Emit exit block
+ f.add(exit_block);
+ set_insert_point(exit_block);
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(
+ x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(
+ x.id, current_function_name
+ + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ value return_val = (*this)(*x.expr);
+ if (!return_val.is_valid())
+ return false;
+ return_var.assign(return_val);
+ }
+
+ branch(return_block);
+ return true;
+ }
+
+ function compiler::function_decl(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ current_function_name = x.function_name.name;
+
+ function f =
+ declare_function(
+ void_return
+ , current_function_name
+ , x.args.size());
+
+ // If function conflicted, the function already exixts. If it has a
+ // body, don't allow redefinition or reextern.
+ if (f.name() != current_function_name)
+ {
+ // Delete the one we just made and get the existing one.
+ f.erase_from_parent();
+ f = get_function(current_function_name);
+
+ // If function already has a body, reject this.
+ if (!f.empty())
+ {
+ error_handler(
+ x.function_name.id,
+ "Duplicate function: " + x.function_name.name);
+ return function();
+ }
+
+ // If function took a different number of args, reject.
+ if (f.arg_size() != x.args.size())
+ {
+ error_handler(
+ x.function_name.id,
+ "Redefinition of function with different # args: "
+ + x.function_name.name);
+ return function();
+ }
+
+ // Set names for all arguments.
+ function::arg_range rng = f.args();
+ function::arg_range::const_iterator iter = rng.begin();
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ iter->name(arg.name);
+ ++iter;
+ }
+ }
+ return f;
+ }
+
+ void compiler::function_allocas(ast::function const& x, function f)
+ {
+ // Create variables for each argument and register the
+ // argument in the symbol table so that references to it will succeed.
+ function::arg_range rng = f.args();
+ function::arg_range::const_iterator iter = rng.begin();
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ // Create an arg_ for this variable.
+ value arg_ = var(arg.name);
+
+ // Store the initial value into the arg_.
+ arg_.assign(*iter);
+
+ // Add arguments to variable symbol table.
+ locals[arg.name] = arg_;
+ ++iter;
+ }
+
+ if (!void_return)
+ {
+ // Create an alloca for the return value
+ return_var = var("return.val");
+ }
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ ///////////////////////////////////////////////////////////////////////
+ // the signature:
+ function f = function_decl(x);
+ if (!f.is_valid())
+ return false;
+
+ ///////////////////////////////////////////////////////////////////////
+ // the body:
+ if (x.body) // compile the body if this is not a prototype
+ {
+ // Create a new basic block to start insertion into.
+ basic_block block = make_basic_block("entry", f);
+ set_insert_point(block);
+
+ function_allocas(x, f);
+ return_block = make_basic_block("return");
+
+ if (!(*this)(*x.body))
+ {
+ // Error reading body, remove function.
+ f.erase_from_parent();
+ return false;
+ }
+
+ basic_block last_block = f.last_block();
+
+ // If the last block is unterminated, connect it to return_block
+ if (!last_block.has_terminator())
+ {
+ set_insert_point(last_block);
+ branch(return_block);
+ }
+
+ f.add(return_block);
+ set_insert_point(return_block);
+
+ if (void_return)
+ return_();
+ else
+ return_(return_var);
+
+ // Validate the generated code, checking for consistency.
+ f.verify();
+
+ // Optimize the function.
+ optimize_function(f);
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ locals.clear(); // clear the variables
+ if (!(*this)(f))
+ return false;
+ }
+ return true;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp
new file mode 100644
index 00000000..ccca3644
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp
@@ -0,0 +1,311 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP)
+#define BOOST_SPIRIT_CONJURE_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include "vm.hpp"
+#include <map>
+
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/iterator/transform_iterator.hpp>
+
+#include <llvm/DerivedTypes.h>
+#include <llvm/Constants.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Analysis/Passes.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Support/IRBuilder.h>
+
+namespace client { namespace code_gen
+{
+ unsigned const int_size = 32;
+ struct compiler;
+ struct llvm_compiler;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Value (light abstraction of an LLVM::Value)
+ ///////////////////////////////////////////////////////////////////////////
+ struct value
+ {
+ value();
+ value(value const& rhs);
+
+ value& operator=(value const& rhs);
+ bool is_lvalue() const;
+ bool is_valid() const;
+ operator bool() const;
+
+ value& assign(value const& rhs);
+
+ void name(char const* id);
+ void name(std::string const& id);
+
+ friend value operator-(value a);
+ friend value operator!(value a);
+ friend value operator+(value a, value b);
+ friend value operator-(value a, value b);
+ friend value operator*(value a, value b);
+ friend value operator/(value a, value b);
+ friend value operator%(value a, value b);
+
+ friend value operator&(value a, value b);
+ friend value operator|(value a, value b);
+ friend value operator^(value a, value b);
+ friend value operator<<(value a, value b);
+ friend value operator>>(value a, value b);
+
+ friend value operator==(value a, value b);
+ friend value operator!=(value a, value b);
+ friend value operator<(value a, value b);
+ friend value operator<=(value a, value b);
+ friend value operator>(value a, value b);
+ friend value operator>=(value a, value b);
+
+ private:
+
+ struct to_llvm_value;
+ friend struct to_llvm_value;
+ friend struct llvm_compiler;
+
+ value(
+ llvm::Value* v,
+ bool is_lvalue_,
+ llvm::IRBuilder<>* builder);
+
+ llvm::LLVMContext& context() const
+ { return llvm::getGlobalContext(); }
+
+ operator llvm::Value*() const;
+
+ llvm::Value* v;
+ bool is_lvalue_;
+ llvm::IRBuilder<>* builder;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Basic Block (light abstraction of an LLVM::BasicBlock)
+ ///////////////////////////////////////////////////////////////////////////
+ struct function;
+
+ struct basic_block
+ {
+ basic_block()
+ : b(0) {}
+
+ bool has_terminator() const;
+ bool is_valid() const;
+
+ private:
+
+ basic_block(llvm::BasicBlock* b)
+ : b(b) {}
+
+ operator llvm::BasicBlock*() const
+ { return b; }
+
+ friend struct llvm_compiler;
+ friend struct function;
+ llvm::BasicBlock* b;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Function (light abstraction of an LLVM::Function)
+ ///////////////////////////////////////////////////////////////////////////
+ struct llvm_compiler;
+
+ struct function
+ {
+ private:
+
+ struct to_value;
+ typedef llvm::Function::arg_iterator arg_iterator;
+ typedef boost::transform_iterator<
+ to_value, arg_iterator>
+ arg_val_iterator;
+
+ public:
+
+ typedef boost::iterator_range<arg_val_iterator> arg_range;
+
+ function()
+ : f(0), c(c) {}
+
+ std::string name() const;
+
+ std::size_t arg_size() const;
+ arg_range args() const;
+
+ void add(basic_block const& b);
+ void erase_from_parent();
+ basic_block last_block();
+ bool empty() const;
+
+ bool is_valid() const;
+ void verify() const;
+
+ private:
+
+ function(llvm::Function* f, llvm_compiler* c)
+ : f(f), c(c) {}
+
+ operator llvm::Function*() const;
+
+ friend struct llvm_compiler;
+ llvm::Function* f;
+ llvm_compiler* c;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The LLVM Compiler. Lower level compiler (does not deal with ASTs)
+ ///////////////////////////////////////////////////////////////////////////
+ struct llvm_compiler
+ {
+ llvm_compiler(vmachine& vm)
+ : llvm_builder(context())
+ , vm(vm)
+ , fpm(vm.module())
+ { init_fpm(); }
+
+ value val() { return value(); }
+ value val(unsigned int x);
+ value val(int x);
+ value val(bool x);
+
+ value var(char const* name);
+ value var(std::string const& name);
+
+ template <typename Container>
+ value call(function callee, Container const& args);
+
+ function get_function(char const* name);
+ function get_function(std::string const& name);
+ function get_current_function();
+
+ function declare_function(
+ bool void_return
+ , std::string const& name
+ , std::size_t nargs);
+
+ basic_block make_basic_block(
+ char const* name
+ , function parent = function()
+ , basic_block before = basic_block());
+
+ basic_block get_insert_block();
+ void set_insert_point(basic_block b);
+
+ void conditional_branch(
+ value cond, basic_block true_br, basic_block false_br);
+ void branch(basic_block b);
+
+ void return_();
+ void return_(value v);
+
+ void optimize_function(function f);
+
+ protected:
+
+ llvm::LLVMContext& context() const
+ { return llvm::getGlobalContext(); }
+
+ llvm::IRBuilder<>& builder()
+ { return llvm_builder; }
+
+ private:
+
+ friend struct function::to_value;
+
+ value val(llvm::Value* v);
+
+ template <typename C>
+ llvm::Value* call_impl(
+ function callee,
+ C const& args);
+
+ void init_fpm();
+ llvm::IRBuilder<> llvm_builder;
+ vmachine& vm;
+ llvm::FunctionPassManager fpm;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The main compiler. Generates code from our AST.
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler : llvm_compiler
+ {
+ typedef value result_type;
+
+ template <typename ErrorHandler>
+ compiler(vmachine& vm, ErrorHandler& error_handler_)
+ : llvm_compiler(vm)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ value operator()(ast::nil) { BOOST_ASSERT(0); return val(); }
+ value operator()(unsigned int x);
+ value operator()(bool x);
+ value operator()(ast::primary_expr const& x);
+ value operator()(ast::identifier const& x);
+ value operator()(ast::unary_expr const& x);
+ value operator()(ast::function_call const& x);
+ value operator()(ast::expression const& x);
+ value operator()(ast::assignment const& x);
+
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ private:
+
+ value compile_binary_expression(
+ value lhs, value rhs, token_ids::type op);
+
+ value compile_expression(
+ int min_precedence,
+ value lhs,
+ std::list<ast::operation>::const_iterator& rest_begin,
+ std::list<ast::operation>::const_iterator rest_end);
+
+ struct statement_compiler;
+ statement_compiler& as_statement();
+
+ function function_decl(ast::function const& x);
+ void function_allocas(ast::function const& x, function function);
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+
+ bool void_return;
+ std::string current_function_name;
+ std::map<std::string, value> locals;
+ basic_block return_block;
+ value return_var;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp
new file mode 100644
index 00000000..70af0db0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp
@@ -0,0 +1,51 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// The conjure lexer example can be built in 3 different variations:
+//
+// - With a lexer using runtime generated DFA tables
+// - With a lexer using pre-generated (static) DFA tables
+// - With a lexer using a pre-generated custom switch based state machine
+//
+// Use one of the following preprocessor constants to define, which of those
+// will be built:
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_DYNAMIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on pre-generated static DFA tables
+// #define CONJURE_LEXER_STATIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_STATIC_SWITCH 1
+
+///////////////////////////////////////////////////////////////////////////////
+// The default is to use the dynamic table driven lexer
+#if CONJURE_LEXER_DYNAMIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_SWITCH == 0
+
+#define CONJURE_LEXER_DYNAMIC_TABLES 1
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Make sure we have only one lexer type selected
+#if (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_TABLES != 0) || \
+ (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0) || \
+ (CONJURE_LEXER_STATIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0)
+
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp
new file mode 100644
index 00000000..651d34d6
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp
@@ -0,0 +1,483 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUL_25_2011_07_25_53)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUL_25_2011_07_25_53
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ enum {end_state_index, id_index, unique_id_index, state_index, bol_index,
+ eol_index, dead_state_index, dfa_offset};
+
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+ static std::size_t const lookup_[256] = {
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 7, 7, 41, 41, 7, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 7, 8, 41, 41, 41, 41, 9, 41,
+ 10, 11, 12, 13, 14, 15, 41, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 41, 19, 20, 21, 22, 41,
+ 41, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 41, 41, 41, 41, 18,
+ 41, 23, 18, 18, 24, 25, 26, 18,
+ 27, 28, 18, 18, 29, 18, 30, 31,
+ 18, 18, 32, 33, 34, 35, 36, 37,
+ 18, 18, 18, 38, 39, 40, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41 };
+ static std::size_t const dfa_alphabet_ = 42;
+ static std::size_t const dfa_[2604] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 27, 13, 11, 20, 21, 18, 16,
+ 24, 17, 19, 2, 26, 25, 14, 12,
+ 15, 26, 26, 7, 4, 26, 6, 26,
+ 26, 26, 9, 26, 3, 26, 5, 8,
+ 22, 10, 23, 0, 1, 35, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 28, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 29,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 30, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 32, 26,
+ 26, 26, 31, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 33, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 34, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 35, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 36, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 61, 26, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 262177, 20, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 39,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131091, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 40, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131093,
+ 14, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 41, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 393241, 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 393242, 17, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131099, 18, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131100,
+ 19, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 42, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 40, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 41, 22, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 123, 23, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 125,
+ 24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 44, 25, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 59, 27, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 34,
+ 30, 0, 0, 0, 0, 27, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 43, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 44,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 45, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 46, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65538, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 47, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 48, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 49, 26, 26, 26, 0, 0, 0, 0,
+ 1, 131084, 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 131085, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 131089, 10, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 131090,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 131092, 13, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 131094, 15, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 42, 42, 42, 42, 42,
+ 50, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 51,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 43, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 52, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65537, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 53,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 32, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 54, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 32, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 55, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 56, 56, 56, 56, 56,
+ 50, 56, 56, 56, 57, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 1, 36,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65536, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65539, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 32, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 58, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 59, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 33, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 65540, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 32,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 61, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 57, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 65541, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0 };
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
+ Iterator curr_ = start_token_;
+ bool end_state_ = *ptr_ != 0;
+ std::size_t id_ = *(ptr_ + id_index);
+ std::size_t uid_ = *(ptr_ + unique_id_index);
+ Iterator end_token_ = start_token_;
+
+ while (curr_ != end_)
+ {
+ std::size_t const state_ =
+ ptr_[lookup_[static_cast<unsigned char>(*curr_++)]];
+
+ if (state_ == 0) break;
+
+ ptr_ = &dfa_[state_ * dfa_alphabet_];
+
+ if (*ptr_)
+ {
+ end_state_ = true;
+ id_ = *(ptr_ + id_index);
+ uid_ = *(ptr_ + unique_id_index);
+ end_token_ = curr_;
+ }
+ }
+
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp
new file mode 100644
index 00000000..1ba8fac0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp
@@ -0,0 +1,43 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This small utility program generates the 2 static lexers, the static table
+// driven and the static switch based lexer.
+
+#include <fstream>
+#include <iostream>
+
+#include "lexer_def.hpp"
+#include <boost/spirit/include/lex_generate_static_lexertl.hpp>
+
+int main()
+{
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+
+ lexer_type lexer;
+
+ // first generate the static switch based lexer
+ std::ofstream out_static("conjure_static_switch_lexer.hpp");
+
+ bool result = boost::spirit::lex::lexertl::generate_static_switch(
+ lexer, out_static, "conjure_static_switch");
+ if (!result) {
+ std::cerr << "Failed to generate static switch based lexer\n";
+ return -1;
+ }
+
+ // now generate the static table based lexer
+ std::ofstream out("conjure_static_lexer.hpp");
+ result = boost::spirit::lex::lexertl::generate_static(
+ lexer, out, "conjure_static");
+ if (!result) {
+ std::cerr << "Failed to generate static table based lexer\n";
+ return -1;
+ }
+
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp
new file mode 100644
index 00000000..0dcd1ac7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp
@@ -0,0 +1,873 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUL_25_2011_07_25_53)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUL_25_2011_07_25_53
+
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static_switch[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static_switch = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static_switch (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ Iterator curr_ = start_token_;
+ bool end_state_ = false;
+ std::size_t id_ = npos;
+ std::size_t uid_ = npos;
+ Iterator end_token_ = start_token_;
+
+ char ch_ = 0;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+
+ if (ch_ == 't') goto state0_2;
+
+ if (ch_ == 'f') goto state0_3;
+
+ if (ch_ == 'v') goto state0_4;
+
+ if (ch_ == 'i') goto state0_5;
+
+ if (ch_ == 'e') goto state0_6;
+
+ if (ch_ == 'w') goto state0_7;
+
+ if (ch_ == 'r') goto state0_8;
+
+ if (ch_ == '|') goto state0_9;
+
+ if (ch_ == '&') goto state0_10;
+
+ if (ch_ == '=') goto state0_11;
+
+ if (ch_ == '!') goto state0_12;
+
+ if (ch_ == '<') goto state0_13;
+
+ if (ch_ == '>') goto state0_14;
+
+ if (ch_ == '+') goto state0_15;
+
+ if (ch_ == '-') goto state0_16;
+
+ if (ch_ == '*') goto state0_17;
+
+ if (ch_ == '/') goto state0_18;
+
+ if (ch_ == '(') goto state0_19;
+
+ if (ch_ == ')') goto state0_20;
+
+ if (ch_ == '{') goto state0_21;
+
+ if (ch_ == '}') goto state0_22;
+
+ if (ch_ == ',') goto state0_23;
+
+ if (ch_ == ';') goto state0_24;
+
+ if ((ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'g' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'q') || ch_ == 's' || ch_ == 'u' || (ch_ >= 'x' && ch_ <= 'z')) goto state0_25;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_1:
+ end_state_ = true;
+ id_ = 35;
+ uid_ = 0;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+ goto end;
+
+state0_2:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_27;
+ goto end;
+
+state0_3:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'b' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'a') goto state0_28;
+ goto end;
+
+state0_4:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'n') || (ch_ >= 'p' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'o') goto state0_29;
+ goto end;
+
+state0_5:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'e') || (ch_ >= 'g' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_30;
+
+ if (ch_ == 'f') goto state0_31;
+ goto end;
+
+state0_6:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_32;
+ goto end;
+
+state0_7:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'g') || (ch_ >= 'i' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'h') goto state0_33;
+ goto end;
+
+state0_8:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_34;
+ goto end;
+
+state0_9:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '|') goto state0_35;
+ goto end;
+
+state0_10:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '&') goto state0_36;
+ goto end;
+
+state0_11:
+ end_state_ = true;
+ id_ = 61;
+ uid_ = 26;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_37;
+ goto end;
+
+state0_12:
+ end_state_ = true;
+ id_ = 262177;
+ uid_ = 20;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_38;
+ goto end;
+
+state0_13:
+ end_state_ = true;
+ id_ = 131091;
+ uid_ = 12;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_39;
+ goto end;
+
+state0_14:
+ end_state_ = true;
+ id_ = 131093;
+ uid_ = 14;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_40;
+ goto end;
+
+state0_15:
+ end_state_ = true;
+ id_ = 393241;
+ uid_ = 16;
+ end_token_ = curr_;
+ goto end;
+
+state0_16:
+ end_state_ = true;
+ id_ = 393242;
+ uid_ = 17;
+ end_token_ = curr_;
+ goto end;
+
+state0_17:
+ end_state_ = true;
+ id_ = 131099;
+ uid_ = 18;
+ end_token_ = curr_;
+ goto end;
+
+state0_18:
+ end_state_ = true;
+ id_ = 131100;
+ uid_ = 19;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_41;
+ goto end;
+
+state0_19:
+ end_state_ = true;
+ id_ = 40;
+ uid_ = 21;
+ end_token_ = curr_;
+ goto end;
+
+state0_20:
+ end_state_ = true;
+ id_ = 41;
+ uid_ = 22;
+ end_token_ = curr_;
+ goto end;
+
+state0_21:
+ end_state_ = true;
+ id_ = 123;
+ uid_ = 23;
+ end_token_ = curr_;
+ goto end;
+
+state0_22:
+ end_state_ = true;
+ id_ = 125;
+ uid_ = 24;
+ end_token_ = curr_;
+ goto end;
+
+state0_23:
+ end_state_ = true;
+ id_ = 44;
+ uid_ = 25;
+ end_token_ = curr_;
+ goto end;
+
+state0_24:
+ end_state_ = true;
+ id_ = 59;
+ uid_ = 27;
+ end_token_ = curr_;
+ goto end;
+
+state0_25:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_26:
+ end_state_ = true;
+ id_ = 34;
+ uid_ = 30;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_27:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_42;
+ goto end;
+
+state0_28:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_43;
+ goto end;
+
+state0_29:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_44;
+ goto end;
+
+state0_30:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_45;
+ goto end;
+
+state0_31:
+ end_state_ = true;
+ id_ = 65538;
+ uid_ = 4;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_32:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_46;
+ goto end;
+
+state0_33:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_47;
+ goto end;
+
+state0_34:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_48;
+ goto end;
+
+state0_35:
+ end_state_ = true;
+ id_ = 131084;
+ uid_ = 8;
+ end_token_ = curr_;
+ goto end;
+
+state0_36:
+ end_state_ = true;
+ id_ = 131085;
+ uid_ = 9;
+ end_token_ = curr_;
+ goto end;
+
+state0_37:
+ end_state_ = true;
+ id_ = 131089;
+ uid_ = 10;
+ end_token_ = curr_;
+ goto end;
+
+state0_38:
+ end_state_ = true;
+ id_ = 131090;
+ uid_ = 11;
+ end_token_ = curr_;
+ goto end;
+
+state0_39:
+ end_state_ = true;
+ id_ = 131092;
+ uid_ = 13;
+ end_token_ = curr_;
+ goto end;
+
+state0_40:
+ end_state_ = true;
+ id_ = 131094;
+ uid_ = 15;
+ end_token_ = curr_;
+ goto end;
+
+state0_41:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_41;
+
+ if (ch_ == '*') goto state0_49;
+ goto end;
+
+state0_42:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_50;
+ goto end;
+
+state0_43:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_42;
+ goto end;
+
+state0_44:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'c') || (ch_ >= 'e' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'd') goto state0_51;
+ goto end;
+
+state0_45:
+ end_state_ = true;
+ id_ = 65537;
+ uid_ = 3;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_46:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_52;
+ goto end;
+
+state0_47:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_53;
+ goto end;
+
+state0_48:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_54;
+ goto end;
+
+state0_49:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_49;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+ goto end;
+
+state0_50:
+ end_state_ = true;
+ id_ = 36;
+ uid_ = 1;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_51:
+ end_state_ = true;
+ id_ = 65536;
+ uid_ = 2;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_52:
+ end_state_ = true;
+ id_ = 65539;
+ uid_ = 5;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_53:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_57;
+ goto end;
+
+state0_54:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_58;
+ goto end;
+
+state0_55:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_55;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_56:
+ end_state_ = true;
+ id_ = 33;
+ uid_ = 29;
+ end_token_ = curr_;
+ goto end;
+
+state0_57:
+ end_state_ = true;
+ id_ = 65540;
+ uid_ = 6;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_58:
+ end_state_ = true;
+ id_ = 32;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_60;
+ goto end;
+
+state0_59:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_60:
+ end_state_ = true;
+ id_ = 65541;
+ uid_ = 7;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+
+end:
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static_switch
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static_switch;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static_switch[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static_switch(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp
new file mode 100644
index 00000000..efda9a6a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp
@@ -0,0 +1,99 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator, typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(BaseIterator first, BaseIterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ // retrieve underlying iterator from current token, err_pos points
+ // to the last validly matched token, so we use its end iterator
+ // as the error position
+ BaseIterator err_pos_base = err_pos->matched().end();
+
+ int line;
+ BaseIterator line_start = get_pos(err_pos_base, line);
+ if (err_pos_base != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos_base; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ BaseIterator get_pos(BaseIterator err_pos, int& line) const
+ {
+ line = 1;
+ BaseIterator i = first;
+ BaseIterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(BaseIterator err_pos) const
+ {
+ BaseIterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ BaseIterator first;
+ BaseIterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp
new file mode 100644
index 00000000..5b51ce36
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::expression<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp
new file mode 100644
index 00000000..eec9cd6a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp
@@ -0,0 +1,59 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CONJURE_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct expression : qi::grammar<Iterator, ast::expression()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ expression(error_handler_type& error_handler, Lexer const& l);
+
+ Lexer const& lexer;
+
+ qi::rule<Iterator, ast::expression()> expr;
+ qi::rule<Iterator, ast::operand()> unary_expr, postfix_expr;
+ qi::rule<Iterator, ast::function_call()> function_call;
+ qi::rule<Iterator, std::list<ast::expression>()> argument_list;
+ qi::rule<Iterator, std::string()> identifier;
+ qi::rule<Iterator, ast::primary_expr()> primary_expr;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp
new file mode 100644
index 00000000..2d21323a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp
@@ -0,0 +1,104 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/lex_plain_token.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ expression<Iterator, Lexer>::expression(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : expression::base_type(expr), lexer(l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::tokenid_mask_type tokenid_mask;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ unary_expr
+ >> *(tokenid_mask(token_ids::op_binary) > unary_expr)
+ ;
+
+ unary_expr =
+ postfix_expr
+ | (tokenid_mask(token_ids::op_unary) > unary_expr)
+ ;
+
+ postfix_expr =
+ function_call
+ | primary_expr
+ ;
+
+ primary_expr =
+ lexer.lit_uint
+ | lexer.true_or_false
+ | identifier
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier = lexer.identifier;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (unary_expr)
+ (postfix_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in unary_expr, postfix_expr,
+ // and primary_expr call annotation.
+ on_success(unary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(postfix_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp
new file mode 100644
index 00000000..98c8169b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "function_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::function<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp
new file mode 100644
index 00000000..fc5263f1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp
@@ -0,0 +1,36 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_FUNCTION_HPP)
+#define BOOST_SPIRIT_CONJURE_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct function : qi::grammar<Iterator, ast::function()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ function(error_handler_type& error_handler, Lexer const& l);
+
+ statement<Iterator, Lexer> body;
+
+ qi::rule<Iterator, ast::identifier()> identifier;
+ qi::rule<Iterator, std::list<ast::identifier>()> argument_list;
+ qi::rule<Iterator, ast::function()> start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp
new file mode 100644
index 00000000..95846264
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp
@@ -0,0 +1,64 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ function<Iterator, Lexer>::function(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : function::base_type(start), body(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ identifier = body.expr.identifier;
+ argument_list = -(identifier % ',');
+
+ start = (l.token("void") | l.token("int"))
+ > identifier
+ > '(' > argument_list > ')'
+ > (';' | '{' > body > '}')
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp
new file mode 100644
index 00000000..c4d98acc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/ids.hpp
@@ -0,0 +1,160 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_IDS_HPP)
+#define BOOST_SPIRIT_CONJURE_IDS_HPP
+
+namespace client
+{
+ struct op_type
+ {
+ enum type
+ {
+ binary = 0x20000,
+ unary = 0x40000,
+ postfix_unary = 0x80000,
+ assign = 0x100000
+ };
+ };
+
+ struct op
+ {
+ enum type
+ {
+ // binary
+ comma,
+ assign,
+ plus_assign,
+ minus_assign,
+ times_assign,
+ divide_assign,
+ mod_assign,
+ bit_and_assign,
+ bit_xor_assign,
+ bit_or_assign,
+ shift_left_assign,
+ shift_right_assign,
+ logical_or,
+ logical_and,
+ bit_or,
+ bit_xor,
+ bit_and,
+ equal,
+ not_equal,
+ less,
+ less_equal,
+ greater,
+ greater_equal,
+ shift_left,
+ shift_right,
+ plus,
+ minus,
+ times,
+ divide,
+ mod,
+
+ // unary
+ plus_plus,
+ minus_minus,
+ compl_,
+ not_,
+ };
+ };
+
+ template <int type, int op>
+ struct make_op
+ {
+ static int const value = type + op;
+ };
+
+ template <op::type op>
+ struct unary_op : make_op<op_type::unary, op> {};
+
+ template <op::type op>
+ struct binary_op
+ : make_op<op_type::binary, op> {};
+
+ template <op::type op>
+ struct assign_op
+ : make_op<op_type::assign, op> {};
+
+ template <op::type op>
+ struct binary_or_unary_op
+ : make_op<op_type::unary | op_type::binary, op> {};
+
+ struct token_ids
+ {
+ enum type
+ {
+ // pseudo tags
+ invalid = -1,
+ op_binary = op_type::binary,
+ op_unary = op_type::unary,
+ op_assign = op_type::assign,
+
+ // binary / unary operators with common tokens
+ // '+' and '-' can be binary or unary
+ // (the lexer cannot distinguish which)
+ plus = binary_or_unary_op<op::plus>::value,
+ minus = binary_or_unary_op<op::minus>::value,
+
+ // binary operators
+ comma = binary_op<op::comma>::value,
+ assign = assign_op<op::assign>::value,
+ plus_assign = assign_op<op::plus_assign>::value,
+ minus_assign = assign_op<op::minus_assign>::value,
+ times_assign = assign_op<op::times_assign>::value,
+ divide_assign = assign_op<op::divide_assign>::value,
+ mod_assign = assign_op<op::mod_assign>::value,
+ bit_and_assign = assign_op<op::bit_and_assign>::value,
+ bit_xor_assign = assign_op<op::bit_xor_assign>::value,
+ bit_or_assign = assign_op<op::bit_or_assign>::value,
+ shift_left_assign = assign_op<op::shift_left_assign>::value,
+ shift_right_assign = assign_op<op::shift_right_assign>::value,
+ logical_or = binary_op<op::logical_or>::value,
+ logical_and = binary_op<op::logical_and>::value,
+ bit_or = binary_op<op::bit_or>::value,
+ bit_xor = binary_op<op::bit_xor>::value,
+ bit_and = binary_op<op::bit_and>::value,
+ equal = binary_op<op::equal>::value,
+ not_equal = binary_op<op::not_equal>::value,
+ less = binary_op<op::less>::value,
+ less_equal = binary_op<op::less_equal>::value,
+ greater = binary_op<op::greater>::value,
+ greater_equal = binary_op<op::greater_equal>::value,
+ shift_left = binary_op<op::shift_left>::value,
+ shift_right = binary_op<op::shift_right>::value,
+ times = binary_op<op::times>::value,
+ divide = binary_op<op::divide>::value,
+ mod = binary_op<op::mod>::value,
+
+ // unary operators with overlaps
+ // '++' and '--' can be prefix or postfix
+ // (the lexer cannot distinguish which)
+ plus_plus = make_op<
+ op_type::unary
+ | op_type::postfix_unary, op::plus_plus>::value,
+
+ minus_minus = make_op<
+ op_type::unary
+ | op_type::postfix_unary, op::minus_minus>::value,
+
+ // unary operators
+ compl_ = unary_op<op::compl_>::value,
+ not_ = unary_op<op::not_>::value,
+
+ // misc tags
+ identifier = op::not_ + 1,
+ comment,
+ whitespace,
+ lit_uint,
+ true_or_false
+ };
+ };
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp
new file mode 100644
index 00000000..d7125fed
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp
@@ -0,0 +1,17 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+template client::lexer::conjure_tokens<base_iterator_type>::conjure_tokens();
+template bool client::lexer::conjure_tokens<base_iterator_type>::add_(
+ std::string const&, int);
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp
new file mode 100644
index 00000000..9624fe2f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp
@@ -0,0 +1,144 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_HPP
+
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/lex_lexertl_position_token.hpp>
+
+#include "config.hpp"
+#include "ids.hpp"
+
+#if CONJURE_LEXER_STATIC_TABLES != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_lexer.hpp"
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_switch_lexer.hpp"
+#endif
+#include <boost/assert.hpp>
+
+namespace client { namespace lexer
+{
+ namespace lex = boost::spirit::lex;
+
+ ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ namespace lex = boost::spirit::lex;
+
+ template <typename BaseIterator>
+ struct get_lexer_type
+ {
+ // Our token needs to be able to carry several token values:
+ // std::string, unsigned int, and bool
+ typedef boost::mpl::vector<std::string, unsigned int, bool>
+ token_value_types;
+
+ // Using the position_token class as the token type to be returned
+ // from the lexer iterators allows to retain positional information
+ // as every token instance stores an iterator pair pointing to the
+ // matched input sequence.
+ typedef lex::lexertl::position_token<
+ BaseIterator, token_value_types, boost::mpl::false_
+ > token_type;
+
+#if CONJURE_LEXER_DYNAMIC_TABLES != 0
+ // use the lexer based on runtime generated DFA tables
+ typedef lex::lexertl::actor_lexer<token_type> type;
+#elif CONJURE_LEXER_STATIC_TABLES != 0
+ // use the lexer based on pre-generated static DFA tables
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static
+ > type;
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+ // use the lexer based on pre-generated static code
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static_switch
+ > type;
+#else
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator>
+ struct conjure_tokens
+ : lex::lexer<typename detail::get_lexer_type<BaseIterator>::type>
+ {
+ private:
+ // get the type of any qi::raw_token(...) and qi::token(...) constructs
+ typedef typename boost::spirit::result_of::terminal<
+ boost::spirit::tag::raw_token(token_ids::type)
+ >::type raw_token_spec;
+
+ typedef typename boost::spirit::result_of::terminal<
+ boost::spirit::tag::token(token_ids::type)
+ >::type token_spec;
+
+ typedef std::map<std::string, token_ids::type> keyword_map_type;
+
+ protected:
+ // add a keyword to the mapping table
+ bool add_(std::string const& keyword, int id = token_ids::invalid);
+
+ struct keyword_adder
+ {
+ conjure_tokens& l;
+ keyword_adder(conjure_tokens& l) : l(l) {}
+ keyword_adder& operator()(
+ std::string const& keyword, int id = token_ids::invalid)
+ {
+ l.add_(keyword, id);
+ return *this;
+ }
+ };
+
+ friend struct keyword_adder;
+ keyword_adder add;
+
+ public:
+ typedef BaseIterator base_iterator_type;
+
+ conjure_tokens();
+
+ // extract a raw_token(id) for the given registered keyword
+ raw_token_spec operator()(std::string const& kwd) const
+ {
+ namespace qi = boost::spirit::qi;
+ qi::raw_token_type raw_token;
+
+ typename keyword_map_type::const_iterator it = keywords_.find(kwd);
+ BOOST_ASSERT(it != keywords_.end());
+ return raw_token((it != keywords_.end()) ? (*it).second : token_ids::invalid);
+ }
+
+ // extract a token(id) for the given registered keyword
+ token_spec token(std::string const& kwd) const
+ {
+ namespace qi = boost::spirit::qi;
+ qi::token_type token;
+
+ typename keyword_map_type::const_iterator it = keywords_.find(kwd);
+ BOOST_ASSERT(it != keywords_.end());
+ return token((it != keywords_.end()) ? (*it).second : token_ids::invalid);
+ }
+
+ lex::token_def<std::string> identifier;
+ lex::token_def<unsigned int> lit_uint;
+ lex::token_def<bool> true_or_false;
+ keyword_map_type keywords_;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp
new file mode 100644
index 00000000..29239768
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp
@@ -0,0 +1,100 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "lexer.hpp"
+
+namespace client { namespace lexer
+{
+ template <typename BaseIterator>
+ conjure_tokens<BaseIterator>::conjure_tokens()
+ : identifier("[a-zA-Z_][a-zA-Z_0-9]*", token_ids::identifier)
+ , lit_uint("[0-9]+", token_ids::lit_uint)
+ , true_or_false("true|false", token_ids::true_or_false)
+ , add(*this)
+ {
+ lex::_pass_type _pass;
+
+ this->self = lit_uint | true_or_false;
+
+ this->add
+ ("void")
+ ("int")
+ ("if")
+ ("else")
+ ("while")
+ ("return")
+ ("=", token_ids::assign)
+ ("\\+=", token_ids::plus_assign)
+ ("\\-=", token_ids::minus_assign)
+ ("\\*=", token_ids::times_assign)
+ ("\\/=", token_ids::divide_assign)
+ ("%=", token_ids::mod_assign)
+ ("\\&=", token_ids::bit_and_assign)
+ ("\\^=", token_ids::bit_xor_assign)
+ ("\\|=", token_ids::bit_or_assign)
+ ("<<=", token_ids::shift_left_assign)
+ (">>=", token_ids::shift_right_assign)
+ ("\\|\\|", token_ids::logical_or)
+ ("&&", token_ids::logical_and)
+ ("\\|", token_ids::bit_or)
+ ("\\^", token_ids::bit_xor)
+ ("&", token_ids::bit_and)
+ ("<<", token_ids::shift_left)
+ (">>", token_ids::shift_right)
+ ("==", token_ids::equal)
+ ("!=", token_ids::not_equal)
+ ("<", token_ids::less)
+ ("<=", token_ids::less_equal)
+ (">", token_ids::greater)
+ (">=", token_ids::greater_equal)
+ ("\\+", token_ids::plus)
+ ("\\-", token_ids::minus)
+ ("\\*", token_ids::times)
+ ("\\/", token_ids::divide)
+ ("%", token_ids::mod)
+ ("\\+\\+", token_ids::plus_plus)
+ ("\\-\\-", token_ids::minus_minus)
+ ("~", token_ids::compl_)
+ ("!", token_ids::not_)
+ ;
+
+ this->self += lex::char_('(') | ')' | '{' | '}' | ',' | ';';
+
+ this->self +=
+ identifier
+ | lex::string("(\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/)|(\\/\\/[^\r\n]*)", token_ids::comment)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ | lex::string("[ \t\n\r]+", token_ids::whitespace)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ ;
+ }
+
+ template <typename BaseIterator>
+ bool conjure_tokens<BaseIterator>::add_(
+ std::string const& keyword, int id_)
+ {
+ // add the token to the lexer
+ token_ids::type id;
+ if (id_ == token_ids::invalid)
+ id = token_ids::type(this->get_next_id());
+ else
+ id = token_ids::type(id_);
+
+ this->self.add(keyword, id);
+ // store the mapping for later retrieval
+ std::pair<typename keyword_map_type::iterator, bool> p =
+ keywords_.insert(typename keyword_map_type::value_type(keyword, id));
+
+ return p.second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp
new file mode 100644
index 00000000..9788e56f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp
@@ -0,0 +1,156 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ HK June 3, 2011 ] Adding lexer
+// [ JDG July 18, 2011 ] Switching to LLVM backend
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "config.hpp"
+#include "function.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include "lexer.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+ typedef lexer_type::iterator_type iterator_type;
+
+ lexer_type lexer; // Our lexer
+
+ base_iterator_type first = source_code.begin();
+ base_iterator_type last = source_code.end();
+
+ iterator_type iter = lexer.begin(first, last);
+ iterator_type end = lexer.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<base_iterator_type, iterator_type>
+ error_handler(first, last); // Our error handler
+ client::parser::function<iterator_type, lexer_type>
+ function(error_handler, lexer); // Our parser
+ client::code_gen::compiler
+ compiler(vm, error_handler); // Our compiler
+
+ // note: we don't need a skipper
+ bool success = parse(iter, end, +function, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ // JIT the main function
+ client::function main_function = vm.get_function("main");
+ if (!main_function)
+ {
+ std::cerr << "function main not found" << std::endl;
+ return 1;
+ }
+
+ int nargs = argc-2;
+ if (main_function.arity() != nargs)
+ {
+ std::cerr << "Error: main function requires "
+ << main_function.arity() << " arguments." << std::endl;
+ std::cerr << nargs << " supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ vm.print_assembler();
+
+ // Call the main function
+ int r;
+ char** args = argv + 2;
+ switch (nargs)
+ {
+ case 0: r = main_function(); break;
+
+ case 1: r = main_function(
+ boost::lexical_cast<int>(args[0]));
+ break;
+
+ case 2: r = main_function(
+ boost::lexical_cast<int>(args[0]),
+ boost::lexical_cast<int>(args[1]));
+ break;
+
+ case 3: r = main_function(
+ boost::lexical_cast<int>(args[0]),
+ boost::lexical_cast<int>(args[1]),
+ boost::lexical_cast<int>(args[2]));
+ break;
+
+ default:
+ std::cerr << "Function calls with more " <<
+ "than 3 arguments not supported" << std::endl;
+ return 1;
+ }
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp
new file mode 100644
index 00000000..ca85a61c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::statement<iterator_type, lexer_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp
new file mode 100644
index 00000000..208ca247
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp
@@ -0,0 +1,42 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_STATEMENT_HPP)
+#define BOOST_SPIRIT_CONJURE_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct statement : qi::grammar<Iterator, ast::statement_list()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ statement(error_handler_type& error_handler, Lexer const& l);
+
+ expression<Iterator, Lexer> expr;
+
+ qi::rule<Iterator, ast::statement_list()>
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement()> statement_;
+ qi::rule<Iterator, ast::variable_declaration()> variable_declaration;
+ qi::rule<Iterator, ast::assignment()> assignment;
+ qi::rule<Iterator, ast::if_statement()> if_statement;
+ qi::rule<Iterator, ast::while_statement()> while_statement;
+ qi::rule<Iterator, ast::return_statement()> return_statement;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp
new file mode 100644
index 00000000..4712aa5f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp
@@ -0,0 +1,126 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ statement<Iterator, Lexer>::statement(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : statement::base_type(statement_list), expr(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::tokenid_mask_type tokenid_mask;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ | expr
+ | ';'
+ ;
+
+ variable_declaration =
+ l("int")
+ > expr.identifier
+ > -(l("=") > expr)
+ > ';'
+ ;
+
+ assignment =
+ expr.identifier
+ > tokenid_mask(token_ids::op_assign)
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ l("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ l("else")
+ > statement_
+ )
+ ;
+
+ while_statement =
+ l("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ l("return")
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (statement_)
+ (variable_declaration)
+ (assignment)
+ (if_statement)
+ (while_statement)
+ (compound_statement)
+ (return_statement)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in variable_declaration,
+ // assignment and return_statement, call annotation.
+ on_success(variable_declaration,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp
new file mode 100644
index 00000000..5434046f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp
@@ -0,0 +1,43 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "config.hpp"
+#include "vm.hpp"
+#include <iostream>
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ vmachine::vmachine()
+ {
+ llvm::InitializeNativeTarget();
+ llvm::LLVMContext& context = llvm::getGlobalContext();
+
+ // Make the module, which holds all the code.
+ module_ = new llvm::Module("Conjure JIT", context);
+
+ // Create the JIT. This takes ownership of the module.
+ std::string error;
+ execution_engine_ =
+ llvm::EngineBuilder(module_).setErrorStr(&error).create();
+
+ BOOST_ASSERT(execution_engine_ != 0);
+ if (!execution_engine_)
+ {
+ std::cerr <<
+ "Could not create ExecutionEngine: " <<
+ error << std::endl;
+
+ exit(1);
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp
new file mode 100644
index 00000000..68698920
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_VM_HPP)
+#define BOOST_SPIRIT_CONJURE_VM_HPP
+
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Target/TargetSelect.h>
+
+#include <boost/assert.hpp>
+
+namespace client
+{
+ class vmachine;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // A light wrapper to a function pointer returning int and accepting
+ // from 0 to 3 arguments, where arity is determined at runtime.
+ ///////////////////////////////////////////////////////////////////////////
+ class function
+ {
+ public:
+
+ typedef int result_type;
+
+ int operator()() const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 0);
+ int (*fp)() = (int(*)())(intptr_t)fptr;
+ return fp();
+ }
+
+ int operator()(int _1) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 1);
+ int (*fp)(int) = (int(*)(int))(intptr_t)fptr;
+ return fp(_1);
+ }
+
+ int operator()(int _1, int _2) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 2);
+ int (*fp)(int, int) = (int(*)(int, int))(intptr_t)fptr;
+ return fp(_1, _2);
+ }
+
+ int operator()(int _1, int _2, int _3) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 3);
+ int (*fp)(int, int, int) = (int(*)(int, int, int))(intptr_t)fptr;
+ return fp(_1, _2, _3);
+ }
+
+ unsigned arity() const { return arity_; }
+ bool operator!() const { return fptr == 0; }
+
+ private:
+
+ friend class vmachine;
+ function(void* fptr, unsigned arity_)
+ : fptr(fptr), arity_(arity_) {}
+
+ void* fptr;
+ unsigned arity_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine (light wrapper over LLVM JIT)
+ ///////////////////////////////////////////////////////////////////////////
+ class vmachine
+ {
+ public:
+
+ vmachine();
+
+ llvm::Module* module() const
+ {
+ return module_;
+ }
+
+ llvm::ExecutionEngine* execution_engine() const
+ {
+ return execution_engine_;
+ }
+
+ void print_assembler() const
+ {
+ module_->dump();
+ }
+
+ function get_function(char const* name)
+ {
+ llvm::Function* callee = module_->getFunction(name);
+ if (callee == 0)
+ return function(0, 0);
+
+ // JIT the function
+ void *fptr = execution_engine_->getPointerToFunction(callee);
+ return function(fptr, callee->arg_size());
+ }
+
+ private:
+
+ llvm::Module* module_;
+ llvm::ExecutionEngine* execution_engine_;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/error.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/error.cnj
new file mode 100644
index 00000000..2c7c0a94
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/error.cnj
@@ -0,0 +1,16 @@
+/* conjure program with syntax error */
+
+int foo(n)
+{
+ int a = 2;
+ if (n @ 3) /* we don't have @ operator in conjure */
+ {
+ a = 3
+ }
+ return a;
+}
+
+int main()
+{
+ return foo(10);
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/factorial.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/factorial.cnj
new file mode 100644
index 00000000..5ea05731
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/factorial.cnj
@@ -0,0 +1,15 @@
+/* The factorial */
+
+int factorial(n)
+{
+ if (n <= 0)
+ return 1;
+ else
+ return n * factorial(n-1);
+}
+
+int main(n)
+{
+ return factorial(n);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/operators.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/operators.cnj
new file mode 100644
index 00000000..8f8aad56
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/operators.cnj
@@ -0,0 +1,137 @@
+/* More operators tests */
+/* Conjure >=3 only!!! */
+
+// assign ops
+
+int aplus(x, y)
+{
+ int t = x;
+ t += y;
+ return t;
+}
+
+int aminus(x, y)
+{
+ int t = x;
+ t -= y;
+ return t;
+}
+
+int ashl(x, y)
+{
+ int t = x;
+ t <<= y;
+ return t;
+}
+
+int adiv(x, y)
+{
+ int t = x;
+ t /= y;
+ return t;
+}
+
+int amult(x, y)
+{
+ int t = x;
+ t *= y;
+ return t;
+}
+
+int amod(x, y)
+{
+ int t = x;
+ t %= y;
+ return t;
+}
+
+int aor(x, y)
+{
+ int t = x;
+ t |= y;
+ return t;
+}
+
+int aand(x, y)
+{
+ int t = x;
+ t &= y;
+ return t;
+}
+
+int axor(x, y)
+{
+ int t = x;
+ t ^= y;
+ return t;
+}
+
+int ashr(x, y)
+{
+ int t = x;
+ t >>= y;
+ return t;
+}
+
+// binary ops
+
+int plus(x, y) { return x + y; }
+int minus(x, y) { return x - y; }
+int shl(x, y) { return x << y; }
+int div(x, y) { return x / y; }
+int mult(x, y) { return x * y; }
+int mod(x, y) { return x % y; }
+int or(x, y) { return x | y; }
+int and(x, y) { return x & y; }
+int xor(x, y) { return x ^ y; }
+int shr(x, y) { return x >> y; }
+
+int assign()
+{
+ int a = aplus(2, 3); // 5
+ int b = ashl(a, 2); // 20
+ int c = aminus(b, 2); // 18
+ int d = adiv(c, 2); // 9
+ int e = amult(d, c); // 162
+ int f = amod(e, 10); // 2
+ int g = aor(f, 45); // 47
+ int h = aand(g, 48); // 32
+ int j = axor(h, h); // 0
+ int k = aor(j, 65535); // 65535
+ int l = ashr(k, 3); // 8191
+ return l;
+}
+
+int binary()
+{
+ int a = plus(2, 3); // 5
+ int b = shl(a, 2); // 20
+ int c = minus(b, 2); // 18
+ int d = div(c, 2); // 9
+ int e = mult(d, c); // 162
+ int f = mod(e, 10); // 2
+ int g = or(f, 45); // 47
+ int h = and(g, 48); // 32
+ int j = xor(h, h); // 0
+ int k = or(j, 65535); // 65535
+ int l = shr(k, 3); // 8191
+ return l;
+}
+
+int zero() { return 0; }
+
+int unary()
+{
+ int i = ~zero(); // -1
+ int j = -i; // 1
+ ++j; // 2
+ ++++j; // 4
+ --j; // 3
+ return j;
+}
+
+int main()
+{
+ return assign() + binary() + unary(); // 16385
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/pow2.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/pow2.cnj
new file mode 100644
index 00000000..4d22fd70
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/pow2.cnj
@@ -0,0 +1,19 @@
+/* My first conjure program */
+
+int pow2(n)
+{
+ int a = 2;
+ int i = 1;
+ while (i < n)
+ {
+ a = a * 2;
+ i = i + 1;
+ }
+ return a;
+}
+
+int main()
+{
+ return pow2(10);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/precedence.cnj b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/precedence.cnj
new file mode 100644
index 00000000..eb91b92e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/conjure_samples/precedence.cnj
@@ -0,0 +1,8 @@
+/* testing the shunting yard operator precedence algorithm */
+
+int main()
+{
+ return 1 + 2 + 3 + 5 * 4 * 6 + 5; /* answer is 131 */
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/annotation.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/annotation.hpp
new file mode 100644
index 00000000..9e7e814e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/annotation.hpp
@@ -0,0 +1,95 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_ANNOTATION_HPP)
+#define BOOST_SPIRIT_MINIC_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ void operator()(ast::identifier& x) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ // no-op
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::variable_declaration& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/ast.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/ast.hpp
new file mode 100644
index 00000000..fc755064
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/ast.hpp
@@ -0,0 +1,225 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_AST_HPP)
+#define BOOST_SPIRIT_MINIC_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<function_call>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ enum optoken
+ {
+ op_plus,
+ op_minus,
+ op_times,
+ op_divide,
+ op_positive,
+ op_negative,
+ op_not,
+ op_equal,
+ op_not_equal,
+ op_less,
+ op_less_equal,
+ op_greater,
+ op_greater_equal,
+ op_and,
+ op_or
+ };
+
+ struct unary
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ statement_list body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (client::ast::statement_list, body)
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.cpp
new file mode 100644
index 00000000..5a17ee07
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.cpp
@@ -0,0 +1,538 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "compiler.hpp"
+#include "vm.hpp"
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void function::op(int a)
+ {
+ code.push_back(a);
+ size_ += 1;
+ }
+
+ void function::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ size_ += 2;
+ }
+
+ void function::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ size_ += 3;
+ }
+
+ int const* function::find_var(std::string const& name) const
+ {
+ std::map<std::string, int>::const_iterator i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void function::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = n;
+ }
+
+ void function::link_to(std::string const& name, std::size_t address)
+ {
+ function_calls[address] = name;
+ }
+
+ void function::print_assembler() const
+ {
+ std::vector<int>::const_iterator pc = code.begin() + address;
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ BOOST_FOREACH(pair const& p, variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << " local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != (code.begin() + address + size_))
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += boost::lexical_cast<std::string>(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_call:
+ {
+ line += " op_call ";
+ int nargs = *pc++;
+ std::size_t jump = *pc++;
+ line += boost::lexical_cast<std::string>(nargs) + ", ";
+ BOOST_ASSERT(function_calls.find(jump) != function_calls.end());
+ line += function_calls.find(jump)->second;
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += boost::lexical_cast<std::string>(*pc++);
+ break;
+
+
+ case op_return:
+ line += " op_return";
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ typedef std::pair<std::size_t, std::string> line_info;
+ BOOST_FOREACH(line_info const& l, lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x)
+ {
+ BOOST_ASSERT(current != 0);
+ current->op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::identifier const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.name);
+ if (p == 0)
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return false;
+ }
+ current->op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::operation const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_plus: current->op(op_add); break;
+ case ast::op_minus: current->op(op_sub); break;
+ case ast::op_times: current->op(op_mul); break;
+ case ast::op_divide: current->op(op_div); break;
+
+ case ast::op_equal: current->op(op_eq); break;
+ case ast::op_not_equal: current->op(op_neq); break;
+ case ast::op_less: current->op(op_lt); break;
+ case ast::op_less_equal: current->op(op_lte); break;
+ case ast::op_greater: current->op(op_gt); break;
+ case ast::op_greater_equal: current->op(op_gte); break;
+
+ case ast::op_and: current->op(op_and); break;
+ case ast::op_or: current->op(op_or); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_negative: current->op(op_neg); break;
+ case ast::op_not: current->op(op_not); break;
+ case ast::op_positive: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_call const& x)
+ {
+ BOOST_ASSERT(current != 0);
+
+ if (functions.find(x.function_name.name) == functions.end())
+ {
+ error_handler(x.function_name.id, "Function not found: " + x.function_name.name);
+ return false;
+ }
+
+ boost::shared_ptr<code_gen::function> p = functions[x.function_name.name];
+
+ if (p->nargs() != x.args.size())
+ {
+ error_handler(x.function_name.id, "Wrong number of arguments: " + x.function_name.name);
+ return false;
+ }
+
+ BOOST_FOREACH(ast::expression const& expr, x.args)
+ {
+ if (!(*this)(expr))
+ return false;
+ }
+
+ current->op(
+ op_call,
+ p->nargs(),
+ p->get_address());
+ current->link_to(x.function_name.name, p->get_address());
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ BOOST_FOREACH(ast::operation const& oper, x.rest)
+ {
+ if (!(*this)(oper))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = current->find_var(x.lhs.name);
+ if (p == 0)
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ current->op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ int const* p = current->find_var(x.lhs.name);
+ if (p != 0)
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+ if (x.rhs) // if there's an RHS initializer
+ {
+ bool r = (*this)(*x.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ current->add_var(x.lhs.name);
+ current->op(op_store, *current->find_var(x.lhs.name));
+ }
+ return r;
+ }
+ else
+ {
+ current->add_var(x.lhs.name);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = current->size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ (*current)[skip] = current->size()-skip; // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an else
+ {
+ (*current)[skip] += 2; // adjust for the "else" jump
+ current->op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ (*current)[exit] = current->size()-exit;// now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ BOOST_ASSERT(current != 0);
+ std::size_t loop = current->size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ current->op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = current->size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ current->op(op_jump,
+ int(loop-1) - int(current->size())); // loop back
+ (*current)[exit] = current->size()-exit; // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(x.id, current_function_name + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ if (!(*this)(*x.expr))
+ return false;
+ }
+ current->op(op_return);
+ return true;
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ if (functions.find(x.function_name.name) != functions.end())
+ {
+ error_handler(x.function_name.id, "Duplicate function: " + x.function_name.name);
+ return false;
+ }
+ boost::shared_ptr<code_gen::function>& p = functions[x.function_name.name];
+ p.reset(new code_gen::function(code, x.args.size()));
+ current = p.get();
+ current_function_name = x.function_name.name;
+
+ // op_stk_adj 0 for now. we'll know how many variables
+ // we'll have later and add them
+ current->op(op_stk_adj, 0);
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ current->add_var(arg.name);
+ }
+
+ if (!(*this)(x.body))
+ return false;
+ (*current)[1] = current->nvars(); // now store the actual number of variables
+ // this includes the arguments
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ // Jump to the main function
+ code.push_back(op_jump);
+ code.push_back(0); // we will fill this in later when we finish compiling
+ // and we know where the main function is
+
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ if (!(*this)(f))
+ {
+ code.clear();
+ return false;
+ }
+ }
+ // find the main function
+ boost::shared_ptr<code_gen::function> p =
+ find_function("main");
+
+ if (!p) // main function not found
+ {
+ std::cerr << "Error: main function not defined" << std::endl;
+ return false;
+ }
+ code[1] = p->get_address()-1; // jump to this (main function) address
+
+ return true;
+ }
+
+ void compiler::print_assembler() const
+ {
+ typedef std::pair<std::string, boost::shared_ptr<code_gen::function> > pair;
+ BOOST_FOREACH(pair const& p, functions)
+ {
+ std::cout << ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;" << std::endl;
+ std::cout << p.second->get_address() << ": function " << p.first << std::endl;
+ p.second->print_assembler();
+ }
+ }
+
+ boost::shared_ptr<code_gen::function>
+ compiler::find_function(std::string const& name) const
+ {
+ function_table::const_iterator i = functions.find(name);
+ if (i == functions.end())
+ return boost::shared_ptr<code_gen::function>();
+ else
+ return i->second;
+ }
+}}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.hpp
new file mode 100644
index 00000000..8a3eea72
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/compiler.hpp
@@ -0,0 +1,118 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_COMPILER_HPP)
+#define BOOST_SPIRIT_MINIC_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Function
+ ///////////////////////////////////////////////////////////////////////////
+ struct function
+ {
+ function(std::vector<int>& code, int nargs)
+ : code(code), address(code.size()), size_(0), nargs_(nargs) {}
+
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[address+i]; }
+ int const& operator[](std::size_t i) const { return code[address+i]; }
+ std::size_t size() const { return size_; }
+ std::size_t get_address() const { return address; }
+
+ int nargs() const { return nargs_; }
+ int nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+ void link_to(std::string const& name, std::size_t address);
+
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::map<std::size_t, std::string> function_calls;
+ std::vector<int>& code;
+ std::size_t address;
+ std::size_t size_;
+ std::size_t nargs_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+
+ template <typename ErrorHandler>
+ compiler(ErrorHandler& error_handler_)
+ : current(0)
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+ }
+
+ bool operator()(ast::nil) { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x);
+ bool operator()(bool x);
+ bool operator()(ast::identifier const& x);
+ bool operator()(ast::operation const& x);
+ bool operator()(ast::unary const& x);
+ bool operator()(ast::function_call const& x);
+ bool operator()(ast::expression const& x);
+ bool operator()(ast::assignment const& x);
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ void print_assembler() const;
+
+ boost::shared_ptr<code_gen::function>
+ find_function(std::string const& name) const;
+
+ std::vector<int>& get_code() { return code; }
+ std::vector<int> const& get_code() const { return code; }
+
+ private:
+
+ typedef std::map<std::string, boost::shared_ptr<code_gen::function> > function_table;
+
+ std::vector<int> code;
+ code_gen::function* current;
+ std::string current_function_name;
+ function_table functions;
+ bool void_return;
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/error_handler.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/error_handler.hpp
new file mode 100644
index 00000000..4ba833c6
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/error_handler.hpp
@@ -0,0 +1,93 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_MINIC_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(Iterator first, Iterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ int line;
+ Iterator line_start = get_pos(err_pos, line);
+ if (err_pos != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ Iterator get_pos(Iterator err_pos, int& line) const
+ {
+ line = 1;
+ Iterator i = first;
+ Iterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(Iterator err_pos) const
+ {
+ Iterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ Iterator first;
+ Iterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.cpp
new file mode 100644
index 00000000..32f44adc
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::expression<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.hpp
new file mode 100644
index 00000000..60edceec
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression.hpp
@@ -0,0 +1,79 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_EXPRESSION_HPP)
+#define BOOST_SPIRIT_MINIC_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include "skipper.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct expression : qi::grammar<Iterator, ast::expression(), skipper<Iterator> >
+ {
+ expression(error_handler<Iterator>& error_handler);
+
+ qi::rule<Iterator, ast::expression(), skipper<Iterator> >
+ expr, equality_expr, relational_expr,
+ logical_or_expr, logical_and_expr,
+ additive_expr, multiplicative_expr
+ ;
+
+ qi::rule<Iterator, ast::operand(), skipper<Iterator> >
+ unary_expr, primary_expr
+ ;
+
+ qi::rule<Iterator, ast::function_call(), skipper<Iterator> >
+ function_call
+ ;
+
+ qi::rule<Iterator, std::list<ast::expression>(), skipper<Iterator> >
+ argument_list
+ ;
+
+ qi::rule<Iterator, std::string(), skipper<Iterator> >
+ identifier
+ ;
+
+ qi::symbols<char, ast::optoken>
+ logical_or_op, logical_and_op,
+ equality_op, relational_op,
+ additive_op, multiplicative_op, unary_op
+ ;
+
+ qi::symbols<char>
+ keywords
+ ;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression_def.hpp
new file mode 100644
index 00000000..f6f7c5d6
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/expression_def.hpp
@@ -0,0 +1,181 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ expression<Iterator>::expression(error_handler<Iterator>& error_handler)
+ : expression::base_type(expr)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::char_type char_;
+ qi::uint_type uint_;
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::bool_type bool_;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Tokens
+ logical_or_op.add
+ ("||", ast::op_or)
+ ;
+
+ logical_and_op.add
+ ("&&", ast::op_and)
+ ;
+
+ equality_op.add
+ ("==", ast::op_equal)
+ ("!=", ast::op_not_equal)
+ ;
+
+ relational_op.add
+ ("<", ast::op_less)
+ ("<=", ast::op_less_equal)
+ (">", ast::op_greater)
+ (">=", ast::op_greater_equal)
+ ;
+
+ additive_op.add
+ ("+", ast::op_plus)
+ ("-", ast::op_minus)
+ ;
+
+ multiplicative_op.add
+ ("*", ast::op_times)
+ ("/", ast::op_divide)
+ ;
+
+ unary_op.add
+ ("+", ast::op_positive)
+ ("-", ast::op_negative)
+ ("!", ast::op_not)
+ ;
+
+ keywords.add
+ ("true")
+ ("false")
+ ("if")
+ ("else")
+ ("while")
+ ("int")
+ ("void")
+ ("return")
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ logical_or_expr.alias()
+ ;
+
+ logical_or_expr =
+ logical_and_expr
+ >> *(logical_or_op > logical_and_expr)
+ ;
+
+ logical_and_expr =
+ equality_expr
+ >> *(logical_and_op > equality_expr)
+ ;
+
+ equality_expr =
+ relational_expr
+ >> *(equality_op > relational_expr)
+ ;
+
+ relational_expr =
+ additive_expr
+ >> *(relational_op > additive_expr)
+ ;
+
+ additive_expr =
+ multiplicative_expr
+ >> *(additive_op > multiplicative_expr)
+ ;
+
+ multiplicative_expr =
+ unary_expr
+ >> *(multiplicative_op > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (unary_op > unary_expr)
+ ;
+
+ primary_expr =
+ uint_
+ | function_call
+ | identifier
+ | bool_
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier =
+ !lexeme[keywords >> !(alnum | '_')]
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (logical_or_expr)
+ (logical_and_expr)
+ (equality_expr)
+ (relational_expr)
+ (additive_expr)
+ (multiplicative_expr)
+ (unary_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.cpp
new file mode 100644
index 00000000..ababd4ad
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "function_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::function<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.hpp
new file mode 100644
index 00000000..cef1c82d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function.hpp
@@ -0,0 +1,32 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_FUNCTION_HPP)
+#define BOOST_SPIRIT_MINIC_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct function : qi::grammar<Iterator, ast::function(), skipper<Iterator> >
+ {
+ function(error_handler<Iterator>& error_handler);
+
+ statement<Iterator> body;
+ qi::rule<Iterator, std::string(), skipper<Iterator> > name;
+ qi::rule<Iterator, ast::identifier(), skipper<Iterator> > identifier;
+ qi::rule<Iterator, std::list<ast::identifier>(), skipper<Iterator> > argument_list;
+ qi::rule<Iterator, ast::function(), skipper<Iterator> > start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function_def.hpp
new file mode 100644
index 00000000..bd2c7d02
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/function_def.hpp
@@ -0,0 +1,71 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ function<Iterator>::function(error_handler<Iterator>& error_handler)
+ : function::base_type(start), body(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::string_type string;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ name =
+ !body.expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ identifier = name;
+ argument_list = -(identifier % ',');
+
+ start =
+ lexeme[(string("void") | string("int"))
+ >> !(alnum | '_')] // make sure we have whole words
+ > identifier
+ > '(' > argument_list > ')'
+ > '{' > body > '}'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/main.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/main.cpp
new file mode 100644
index 00000000..27d4bee0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/main.cpp
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "function.hpp"
+#include "skipper.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator iterator_type;
+ iterator_type iter = source_code.begin();
+ iterator_type end = source_code.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<iterator_type>
+ error_handler(iter, end); // Our error handler
+ client::parser::function<iterator_type>
+ function(error_handler); // Our parser
+ client::parser::skipper<iterator_type>
+ skipper; // Our skipper
+ client::code_gen::compiler
+ compiler(error_handler); // Our compiler
+
+
+ bool success = phrase_parse(iter, end, +function, skipper, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ boost::shared_ptr<client::code_gen::function>
+ p = compiler.find_function("main");
+ if (!p)
+ return 1;
+
+ int nargs = argc-2;
+ if (p->nargs() != nargs)
+ {
+ std::cerr << "Error: main function requires " << p->nargs() << " arguments." << std::endl;
+ std::cerr << nargs << "supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ compiler.print_assembler();
+
+ // Push the arguments into our stack
+ for (int i = 0; i < nargs; ++i)
+ vm.get_stack()[i] = boost::lexical_cast<int>(argv[i+2]);
+
+ // Call the interpreter
+ int r = vm.execute(compiler.get_code());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/skipper.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/skipper.hpp
new file mode 100644
index 00000000..041fb9b0
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/skipper.hpp
@@ -0,0 +1,40 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_SKIPPER_HPP)
+#define BOOST_SPIRIT_MINIC_SKIPPER_HPP
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The skipper grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct skipper : qi::grammar<Iterator>
+ {
+ skipper() : skipper::base_type(start)
+ {
+ qi::char_type char_;
+ ascii::space_type space;
+
+ start =
+ space // tab/space/cr/lf
+ | "/*" >> *(char_ - "*/") >> "*/" // C-style comments
+ ;
+ }
+
+ qi::rule<Iterator> start;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.cpp
new file mode 100644
index 00000000..54bc9ac3
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator iterator_type;
+template struct client::parser::statement<iterator_type>;
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.hpp
new file mode 100644
index 00000000..366f8741
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement.hpp
@@ -0,0 +1,38 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_STATEMENT_HPP)
+#define BOOST_SPIRIT_MINIC_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct statement : qi::grammar<Iterator, ast::statement_list(), skipper<Iterator> >
+ {
+ statement(error_handler<Iterator>& error_handler);
+
+ expression<Iterator> expr;
+ qi::rule<Iterator, ast::statement_list(), skipper<Iterator> >
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement(), skipper<Iterator> > statement_;
+ qi::rule<Iterator, ast::variable_declaration(), skipper<Iterator> > variable_declaration;
+ qi::rule<Iterator, ast::assignment(), skipper<Iterator> > assignment;
+ qi::rule<Iterator, ast::if_statement(), skipper<Iterator> > if_statement;
+ qi::rule<Iterator, ast::while_statement(), skipper<Iterator> > while_statement;
+ qi::rule<Iterator, ast::return_statement(), skipper<Iterator> > return_statement;
+ qi::rule<Iterator, std::string(), skipper<Iterator> > identifier;
+ };
+}}
+
+#endif
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement_def.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement_def.hpp
new file mode 100644
index 00000000..f99b665a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/statement_def.hpp
@@ -0,0 +1,124 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator>
+ statement<Iterator>::statement(error_handler<Iterator>& error_handler)
+ : statement::base_type(statement_list), expr(error_handler)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_type raw;
+ qi::lexeme_type lexeme;
+ qi::alpha_type alpha;
+ qi::alnum_type alnum;
+ qi::lit_type lit;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef function<client::error_handler<Iterator> > error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ ;
+
+ identifier =
+ !expr.keywords
+ >> raw[lexeme[(alpha | '_') >> *(alnum | '_')]]
+ ;
+
+ variable_declaration =
+ lexeme["int" >> !(alnum | '_')] // make sure we have whole words
+ > identifier
+ > -('=' > expr)
+ > ';'
+ ;
+
+ assignment =
+ identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ lit("if")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ lexeme["else" >> !(alnum | '_')] // make sure we have whole words
+ > statement_
+ )
+ ;
+
+ while_statement =
+ lit("while")
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ lexeme["return" >> !(alnum | '_')] // make sure we have whole words
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (identifier)
+ (variable_declaration)
+ (assignment)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in variable_declaration,
+ // assignment and return_statement, call annotation.
+ on_success(variable_declaration,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.cpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.cpp
new file mode 100644
index 00000000..8740bf9c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.cpp
@@ -0,0 +1,159 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "vm.hpp"
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (true)
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr += *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.hpp b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.hpp
new file mode 100644
index 00000000..eb4cc294
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c/vm.hpp
@@ -0,0 +1,82 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_MINIC_VM_HPP)
+#define BOOST_SPIRIT_MINIC_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ }
+
+ std::vector<int> const& get_stack() const { return stack; };
+ std::vector<int>& get_stack() { return stack; };
+
+ private:
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/1.mini b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/1.mini
new file mode 100644
index 00000000..bd22c869
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/1.mini
@@ -0,0 +1,19 @@
+/* My first mini program */
+
+int pow2(n)
+{
+ int a = 2;
+ int i = 1;
+ while (i < n)
+ {
+ a = a * 2;
+ i = i + 1;
+ }
+ return a;
+}
+
+int main()
+{
+ return pow2(10);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/2.mini b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/2.mini
new file mode 100644
index 00000000..5ea05731
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/2.mini
@@ -0,0 +1,15 @@
+/* The factorial */
+
+int factorial(n)
+{
+ if (n <= 0)
+ return 1;
+ else
+ return n * factorial(n-1);
+}
+
+int main(n)
+{
+ return factorial(n);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/3.mini b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/3.mini
new file mode 100644
index 00000000..5c407d6e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/compiler_tutorial/mini_c_samples/3.mini
@@ -0,0 +1,17 @@
+/* mini program with syntax error */
+
+int foo(n)
+{
+ int a = 2;
+ if (n @ 3) /* we don't have @ operator in mini_c */
+ {
+ a = 3
+ }
+ return a;
+}
+
+int main()
+{
+ return foo(10);
+}
+
diff --git a/src/boost/libs/spirit/example/qi/complex_number.cpp b/src/boost/libs/spirit/example/qi/complex_number.cpp
new file mode 100644
index 00000000..a4400e0c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/complex_number.cpp
@@ -0,0 +1,101 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A complex number micro parser.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG May 9, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+///////////////////////////////////////////////////////////////////////////////
+// Our complex number parser/compiler
+///////////////////////////////////////////////////////////////////////////////
+//[tutorial_complex_number
+namespace client
+{
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::ascii::space;
+ using boost::phoenix::ref;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ '(' >> double_[ref(rN) = _1]
+ >> -(',' >> double_[ref(iN) = _1]) >> ')'
+ | double_[ref(rN) = _1]
+ ),
+ // End grammar
+
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+}
+//]
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << c << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/custom_string.cpp b/src/boost/libs/spirit/example/qi/custom_string.cpp
new file mode 100644
index 00000000..e5e78221
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/custom_string.cpp
@@ -0,0 +1,113 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example demonstrates the steps needed to integrate a custom container
+// type to be usable with Spirit.Qi. It shows how to utilize the QString data
+// type as a Qi attribute.
+
+// Note: you need to have Qt4 installed on your system and you have to make
+// sure your compiler finds the includes and your linker finds the
+// proper libraries.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+
+#include <Qt/qstring.h>
+
+namespace boost { namespace spirit { namespace traits
+{
+ // Make Qi recognize QString as a container
+ template <> struct is_container<QString> : mpl::true_ {};
+
+ // Expose the container's (QString's) value_type
+ template <> struct container_value<QString> : mpl::identity<QChar> {};
+
+ // Define how to insert a new element at the end of the container (QString)
+ template <>
+ struct push_back_container<QString, QChar>
+ {
+ static bool call(QString& c, QChar const& val)
+ {
+ c.append(val);
+ return true;
+ }
+ };
+
+ // Test if a QString is empty (required for debug)
+ template <>
+ struct is_empty_container<QString>
+ {
+ static bool call(QString const& c)
+ {
+ return c.isEmpty();
+ }
+ };
+
+ // Define how to stream a QString (required for debug)
+ template <typename Out, typename Enable>
+ struct print_attribute_debug<Out, QString, Enable>
+ {
+ static void call(Out& out, QString const& val)
+ {
+ out << val.toStdString();
+ }
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ template <typename Iterator>
+ bool parse_qstring(Iterator first, Iterator last, QString& t)
+ {
+ using boost::spirit::qi::char_;
+ using boost::spirit::ascii::space;
+ using boost::spirit::qi::phrase_parse;
+
+ bool r = phrase_parse(first, last, +char_, space, t);
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+
+ return r;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tParsing into a QString from Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ QString t;
+ if (client::parse_qstring(str.begin(), str.end(), t))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << t.toStdString() << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/display_attribute_type.cpp b/src/boost/libs/spirit/example/qi/display_attribute_type.cpp
new file mode 100644
index 00000000..11f086b5
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/display_attribute_type.cpp
@@ -0,0 +1,22 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example implements a simple utility allowing to print the attribute
+// type as it is exposed by an arbitrary Qi parser expression. Just insert
+// your expression below, compile and run this example to see what Qi is
+// seeing!
+
+#include "display_attribute_type.hpp"
+
+namespace qi = boost::spirit::qi;
+
+int main()
+{
+ tools::display_attribute_of_parser(
+ std::cerr, // put the required output stream here
+ qi::int_ >> qi::double_ // put your parser expression here
+ );
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/display_attribute_type.hpp b/src/boost/libs/spirit/example/qi/display_attribute_type.hpp
new file mode 100644
index 00000000..84c2245d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/display_attribute_type.hpp
@@ -0,0 +1,59 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This example implements a simple utility allowing to print the attribute
+// type as it is exposed by an arbitrary Qi parser expression. Just insert
+// your expression below, compile and run this example to see what Qi is
+// seeing!
+
+#if !defined (DISPLAY_ATTRIBUTE_OF_PARSER_JAN_2010_30_0722PM)
+#define DISPLAY_ATTRIBUTE_OF_PARSER_JAN_2010_30_0722PM
+
+#include <iostream>
+#include <boost/spirit/include/qi.hpp>
+
+namespace tools
+{
+ namespace spirit = boost::spirit;
+
+ template <typename Expr, typename Iterator = spirit::unused_type>
+ struct attribute_of_parser
+ {
+ typedef typename spirit::result_of::compile<
+ spirit::qi::domain, Expr
+ >::type parser_expression_type;
+
+ typedef typename spirit::traits::attribute_of<
+ parser_expression_type, spirit::unused_type, Iterator
+ >::type type;
+ };
+
+ template <typename T>
+ void display_attribute_of_parser(T const &)
+ {
+ // Report invalid expression error as early as possible.
+ // If you got an error_invalid_expression error message here,
+ // then the expression (expr) is not a valid spirit qi expression.
+ BOOST_SPIRIT_ASSERT_MATCH(spirit::qi::domain, T);
+
+ typedef typename attribute_of_parser<T>::type type;
+ std::cout << typeid(type).name() << std::endl;
+ }
+
+ template <typename T>
+ void display_attribute_of_parser(std::ostream& os, T const &)
+ {
+ // Report invalid expression error as early as possible.
+ // If you got an error_invalid_expression error message here,
+ // then the expression (expr) is not a valid spirit qi expression.
+ BOOST_SPIRIT_ASSERT_MATCH(spirit::qi::domain, T);
+
+ typedef typename attribute_of_parser<T>::type type;
+ os << typeid(type).name() << std::endl;
+ }
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/qi/employee.cpp b/src/boost/libs/spirit/example/qi/employee.cpp
new file mode 100644
index 00000000..c303ff8b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/employee.cpp
@@ -0,0 +1,151 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A parser for arbitrary tuples. This example presents a parser
+// for an employee structure.
+//
+// [ JDG May 9, 2007 ]
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our employee struct
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_employee_struct
+ struct employee
+ {
+ int age;
+ std::string surname;
+ std::string forename;
+ double salary;
+ };
+ //]
+}
+
+// We need to tell fusion about our employee struct
+// to make it a first-class fusion citizen. This has to
+// be in global scope.
+
+//[tutorial_employee_adapt_struct
+BOOST_FUSION_ADAPT_STRUCT(
+ client::employee,
+ (int, age)
+ (std::string, surname)
+ (std::string, forename)
+ (double, salary)
+)
+//]
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our employee parser
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_employee_parser
+ template <typename Iterator>
+ struct employee_parser : qi::grammar<Iterator, employee(), ascii::space_type>
+ {
+ employee_parser() : employee_parser::base_type(start)
+ {
+ using qi::int_;
+ using qi::lit;
+ using qi::double_;
+ using qi::lexeme;
+ using ascii::char_;
+
+ quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
+
+ start %=
+ lit("employee")
+ >> '{'
+ >> int_ >> ','
+ >> quoted_string >> ','
+ >> quoted_string >> ','
+ >> double_
+ >> '}'
+ ;
+ }
+
+ qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
+ qi::rule<Iterator, employee(), ascii::space_type> start;
+ };
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tAn employee parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout
+ << "Give me an employee of the form :"
+ << "employee{age, \"surname\", \"forename\", salary } \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ using boost::spirit::ascii::space;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::employee_parser<iterator_type> employee_parser;
+
+ employee_parser g; // Our grammar
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::employee emp;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, g, space, emp);
+
+ if (r && iter == end)
+ {
+ std::cout << boost::fusion::tuple_open('[');
+ std::cout << boost::fusion::tuple_close(']');
+ std::cout << boost::fusion::tuple_delimiter(", ");
+
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << boost::fusion::as_vector(emp) << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/expect.cpp b/src/boost/libs/spirit/example/qi/expect.cpp
new file mode 100644
index 00000000..ecbc24aa
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/expect.cpp
@@ -0,0 +1,112 @@
+/*=============================================================================
+Copyright (c) 2016 Frank Hein, maxence business consulting gmbh
+
+Distributed under the Boost Software License, Version 1.0. (See accompanying
+file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#include <iostream>
+#include <map>
+
+#include <boost/spirit/home/qi.hpp>
+#include <boost/spirit/home/qi/nonterminal/grammar.hpp>
+#include <boost/spirit/include/phoenix.hpp>
+#include <boost/foreach.hpp>
+
+namespace qi = boost::spirit::qi;
+
+typedef std::string::const_iterator iterator_type;
+typedef std::string result_type;
+
+template<typename Parser>
+void parse(const std::string message, const std::string& input, const std::string& rule, const Parser& parser) {
+ iterator_type iter = input.begin(), end = input.end();
+
+ std::vector<result_type> parsed_result;
+
+ std::cout << "-------------------------\n";
+ std::cout << message << "\n";
+ std::cout << "Rule: " << rule << std::endl;
+ std::cout << "Parsing: \"" << input << "\"\n";
+
+ bool result = qi::phrase_parse(iter, end, parser, qi::space, parsed_result);
+ if (result)
+ {
+ std::cout << "Parser succeeded.\n";
+ std::cout << "Parsed " << parsed_result.size() << " elements:";
+ BOOST_FOREACH(result_type const& str, parsed_result)
+ {
+ std::cout << "[" << str << "]";
+ }
+ std::cout << std::endl;
+ }
+ else
+ {
+ std::cout << "Parser failed" << std::endl;
+ }
+ if (iter == end) {
+ std::cout << "EOI reached." << std::endl;
+ }
+ else {
+ std::cout << "EOI not reached. Unparsed: \"" << std::string(iter, end) << "\"" << std::endl;
+ }
+ std::cout << "-------------------------\n";
+
+}
+
+namespace grammars {
+ namespace phx = boost::phoenix;
+
+ template <typename Iterator>
+ struct ident : qi::grammar < Iterator, std::string(), qi::space_type>
+ {
+ ident();
+
+ qi::rule <iterator_type, std::string(), qi::space_type>
+ id, id_list, qualified_id;
+ };
+
+ template <typename Iterator>
+ ident<Iterator>::ident() : ident::base_type(id_list) {
+
+ using qi::on_error;
+ using qi::fail;
+ using qi::expect;
+
+ id = (qi::alpha | qi::char_('_')) >> *(qi::alnum | qi::char_('_'));
+
+ id_list = expect[id >> qi::lit(';')];
+
+ on_error<fail>(id_list,
+ phx::ref(std::cout)
+ << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl
+ << "Error! Expecting "
+ << qi::_4
+ << " here: "
+ << phx::construct<std::string>(qi::_3, qi::_2) << std::endl
+ << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl
+ );
+ }
+}
+
+int main() {
+
+ grammars::ident<iterator_type> id;
+
+ parse("expect directive, fail on first"
+ , "1234; id2;"
+ , "qi::expect[ id >> qi::lit(';') ]"
+ , id);
+
+ parse("expect directive, fail on second"
+ , "id1, id2"
+ , "qi::expect[ id >> qi::lit(';') ]"
+ , id);
+
+ parse("expect directive, success"
+ , "id1;"
+ , "qi::expect[ id >> qi::lit(';') ]"
+ , id);
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/german_floating_point.cpp b/src/boost/libs/spirit/example/qi/german_floating_point.cpp
new file mode 100644
index 00000000..c091ca92
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/german_floating_point.cpp
@@ -0,0 +1,48 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+// Copyright (c) 2011 Michael Caisse
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/spirit/include/qi.hpp>
+
+namespace qi = boost::spirit::qi;
+
+template <typename T>
+struct german_real_policies : qi::real_policies<T>
+{
+ template <typename Iterator>
+ static bool parse_dot(Iterator& first, Iterator const& last)
+ {
+ if (first == last || *first != ',')
+ return false;
+ ++first;
+ return true;
+ }
+};
+
+qi::real_parser<double, german_real_policies<double> > const german_double;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::string input("123,456");
+ std::string::iterator begin = input.begin();
+ std::string::iterator end = input.end();
+
+ double value = 0;
+ if (!qi::parse(begin, end, german_double, value))
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded, got: " << value << "\n";
+ std::cout << "---------------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/iter_pos.hpp b/src/boost/libs/spirit/example/qi/iter_pos.hpp
new file mode 100644
index 00000000..b6259fd7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/iter_pos.hpp
@@ -0,0 +1,83 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#if !defined(ITER_POS_NOV_20_2009_1245PM)
+#define ITER_POS_NOV_20_2009_1245PM
+
+#include <boost/spirit/include/qi_parse.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+// definition the place holder
+namespace custom_parser
+{
+ BOOST_SPIRIT_TERMINAL(iter_pos)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// implementation the enabler
+namespace boost { namespace spirit
+{
+ // We want custom_parser::iter_pos to be usable as a terminal only,
+ // and only for parser expressions (qi::domain).
+ template <>
+ struct use_terminal<qi::domain, custom_parser::tag::iter_pos>
+ : mpl::true_
+ {};
+}}
+
+///////////////////////////////////////////////////////////////////////////////
+// implementation of the parser
+namespace custom_parser
+{
+ struct iter_pos_parser
+ : boost::spirit::qi::primitive_parser<iter_pos_parser>
+ {
+ // Define the attribute type exposed by this parser component
+ template <typename Context, typename Iterator>
+ struct attribute
+ {
+ typedef Iterator type;
+ };
+
+ // This function is called during the actual parsing process
+ template <typename Iterator, typename Context
+ , typename Skipper, typename Attribute>
+ bool parse(Iterator& first, Iterator const& last
+ , Context&, Skipper const& skipper, Attribute& attr) const
+ {
+ boost::spirit::qi::skip_over(first, last, skipper);
+ boost::spirit::traits::assign_to(first, attr);
+ return true;
+ }
+
+ // This function is called during error handling to create
+ // a human readable string for the error context.
+ template <typename Context>
+ boost::spirit::info what(Context&) const
+ {
+ return boost::spirit::info("iter_pos");
+ }
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// instantiation of the parser
+namespace boost { namespace spirit { namespace qi
+{
+ // This is the factory function object invoked in order to create
+ // an instance of our iter_pos_parser.
+ template <typename Modifiers>
+ struct make_primitive<custom_parser::tag::iter_pos, Modifiers>
+ {
+ typedef custom_parser::iter_pos_parser result_type;
+
+ result_type operator()(unused_type, unused_type) const
+ {
+ return result_type();
+ }
+ };
+}}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/qi/iter_pos_parser.cpp b/src/boost/libs/spirit/example/qi/iter_pos_parser.cpp
new file mode 100644
index 00000000..92ff4b00
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/iter_pos_parser.cpp
@@ -0,0 +1,51 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how a simple custom primitive parser
+// component can be written. We develop a custom parser exposing the current
+// iterator position as its attribute.
+//
+// For more information see: http://spirit.sourceforge.net/home/?page_id=567
+
+#include <boost/spirit/include/qi_parse_attr.hpp>
+#include <boost/spirit/include/qi_char.hpp>
+#include <boost/spirit/include/qi_operator.hpp>
+
+#include <string>
+#include "iter_pos.hpp"
+
+namespace qi = boost::spirit::qi;
+
+int main()
+{
+ using custom_parser::iter_pos;
+
+ std::string prefix, suffix; // attributes receiving the
+ std::string::iterator position; // parsed values
+
+ std::string input("prefix1234567");
+ std::string::iterator first = input.begin();
+ bool result =
+ qi::parse(first, input.end()
+ , +qi::alpha >> iter_pos >> +qi::digit
+ , prefix, position, suffix);
+
+ if (result)
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "prefix is: " << prefix << "\n";
+ std::cout << "suffix is: " << suffix << "\n";
+ std::cout << "position is: " << std::distance(input.begin(), position) << "\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/key_value_sequence.cpp b/src/boost/libs/spirit/example/qi/key_value_sequence.cpp
new file mode 100644
index 00000000..3e75786d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/key_value_sequence.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how to parse arbitrary key/value
+// pairs delimited by some separator into a std::map. Parsing the URL query
+// format is the example we use to demonstrate how this can be done
+// (i.e. things like: key1=value1;key2=value2;...;keyN=valueN).
+//
+// For a more elaborate explanation see here: http://spirit.sourceforge.net/home/?p=371
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <map>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ typedef std::map<std::string, std::string> pairs_type;
+
+ template <typename Iterator>
+ struct key_value_sequence
+ : qi::grammar<Iterator, pairs_type()>
+ {
+ key_value_sequence()
+ : key_value_sequence::base_type(query)
+ {
+ query = pair >> *((qi::lit(';') | '&') >> pair);
+ pair = key >> -('=' >> value);
+ key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
+ value = +qi::char_("a-zA-Z_0-9");
+ }
+
+ qi::rule<Iterator, pairs_type()> query;
+ qi::rule<Iterator, std::pair<std::string, std::string>()> pair;
+ qi::rule<Iterator, std::string()> key, value;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace qi = boost::spirit::qi;
+
+ std::string input("key1=value1;key2;key3=value3");
+ std::string::iterator begin = input.begin();
+ std::string::iterator end = input.end();
+
+ client::key_value_sequence<std::string::iterator> p;
+ client::pairs_type m;
+
+ if (!qi::parse(begin, end, p, m))
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded, found entries:\n";
+ client::pairs_type::iterator end = m.end();
+ for (client::pairs_type::iterator it = m.begin(); it != end; ++it)
+ {
+ std::cout << (*it).first;
+ if (!(*it).second.empty())
+ std::cout << "=" << (*it).second;
+ std::cout << std::endl;
+ }
+ std::cout << "---------------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp b/src/boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp
new file mode 100644
index 00000000..8cb8e20d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/key_value_sequence_empty_value.cpp
@@ -0,0 +1,83 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how to parse arbitrary key/value
+// pairs delimited by some separator into a std::vector. The difference to
+// the example 'key_value_sequence.cpp' is that we preserve the order of the
+// elements in the parsed sequence as well as possibly existing duplicates.
+// In addition to the example 'key_value_sequence_ordered.cpp' we allow for
+// empty values, i.e. the grammar allows to distinguish between 'key=;' and
+// 'key;", where the first stores an empty string as the value, while the
+// second does not initialize the optional holding the value.
+//
+// For a more elaborate explanation see here: http://spirit.sourceforge.net/home/?p=371
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <map>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ typedef std::pair<std::string, boost::optional<std::string> > pair_type;
+ typedef std::vector<pair_type> pairs_type;
+
+ template <typename Iterator>
+ struct key_value_sequence_empty_value
+ : qi::grammar<Iterator, pairs_type()>
+ {
+ key_value_sequence_empty_value()
+ : key_value_sequence_empty_value::base_type(query)
+ {
+ query = pair >> *((qi::lit(';') | '&') >> pair);
+ pair = key >> -('=' >> -value);
+ key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
+ value = +qi::char_("a-zA-Z_0-9");
+ }
+
+ qi::rule<Iterator, pairs_type()> query;
+ qi::rule<Iterator, pair_type()> pair;
+ qi::rule<Iterator, std::string()> key, value;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace qi = boost::spirit::qi;
+
+ std::string input("key1=value1;key2;key3=value3;key4=");
+ std::string::iterator begin = input.begin();
+ std::string::iterator end = input.end();
+
+ client::key_value_sequence_empty_value<std::string::iterator> p;
+ client::pairs_type m;
+
+ if (!qi::parse(begin, end, p, m))
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded, found entries:\n";
+ client::pairs_type::iterator end = m.end();
+ for (client::pairs_type::iterator it = m.begin(); it != end; ++it)
+ {
+ std::cout << (*it).first;
+ if ((*it).second)
+ std::cout << "=" << boost::get<std::string>((*it).second);
+ std::cout << std::endl;
+ }
+ std::cout << "---------------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/key_value_sequence_ordered.cpp b/src/boost/libs/spirit/example/qi/key_value_sequence_ordered.cpp
new file mode 100644
index 00000000..21689239
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/key_value_sequence_ordered.cpp
@@ -0,0 +1,78 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The purpose of this example is to show how to parse arbitrary key/value
+// pairs delimited by some separator into a std::vector. The difference to
+// the example 'key_value_sequence.cpp' is that we preserve the order of the
+// elements in the parsed seqeunce as well as possibly existing duplicates.
+//
+// For a more elaborate explanation see here: http://spirit.sourceforge.net/home/?p=371
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+#include <iostream>
+#include <map>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ typedef std::vector<std::pair<std::string, std::string> > pairs_type;
+
+ template <typename Iterator>
+ struct key_value_sequence_ordered
+ : qi::grammar<Iterator, pairs_type()>
+ {
+ key_value_sequence_ordered()
+ : key_value_sequence_ordered::base_type(query)
+ {
+ query = pair >> *((qi::lit(';') | '&') >> pair);
+ pair = key >> -('=' >> value);
+ key = qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9");
+ value = +qi::char_("a-zA-Z_0-9");
+ }
+
+ qi::rule<Iterator, pairs_type()> query;
+ qi::rule<Iterator, std::pair<std::string, std::string>()> pair;
+ qi::rule<Iterator, std::string()> key, value;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace qi = boost::spirit::qi;
+
+ std::string input("key2=value2;key1;key3=value3");
+ std::string::iterator begin = input.begin();
+ std::string::iterator end = input.end();
+
+ client::key_value_sequence_ordered<std::string::iterator> p;
+ client::pairs_type v;
+
+ if (!qi::parse(begin, end, p, v))
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------------- \n";
+ }
+ else
+ {
+ std::cout << "-------------------------------- \n";
+ std::cout << "Parsing succeeded, found entries:\n";
+ client::pairs_type::iterator end = v.end();
+ for (client::pairs_type::iterator it = v.begin(); it != end; ++it)
+ {
+ std::cout << (*it).first;
+ if (!(*it).second.empty())
+ std::cout << "=" << (*it).second;
+ std::cout << std::endl;
+ }
+ std::cout << "---------------------------------\n";
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/mini_xml1.cpp b/src/boost/libs/spirit/example/qi/mini_xml1.cpp
new file mode 100644
index 00000000..1a27eda4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml1.cpp
@@ -0,0 +1,242 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A mini XML-like parser
+//
+// [ JDG March 25, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace fusion = boost::fusion;
+ namespace phoenix = boost::phoenix;
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML tree representation
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_xml1_structures
+ struct mini_xml;
+
+ typedef
+ boost::variant<
+ boost::recursive_wrapper<mini_xml>
+ , std::string
+ >
+ mini_xml_node;
+
+ struct mini_xml
+ {
+ std::string name; // tag name
+ std::vector<mini_xml_node> children; // children
+ };
+ //]
+}
+
+// We need to tell fusion about our mini_xml struct
+// to make it a first-class fusion citizen
+//[tutorial_xml1_adapt_structures
+BOOST_FUSION_ADAPT_STRUCT(
+ client::mini_xml,
+ (std::string, name)
+ (std::vector<client::mini_xml_node>, children)
+)
+//]
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Print out the mini xml tree
+ ///////////////////////////////////////////////////////////////////////////
+ int const tabsize = 4;
+
+ void tab(int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ std::cout << ' ';
+ }
+
+ struct mini_xml_printer
+ {
+ mini_xml_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const;
+
+ int indent;
+ };
+
+ struct mini_xml_node_printer : boost::static_visitor<>
+ {
+ mini_xml_node_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const
+ {
+ mini_xml_printer(indent+tabsize)(xml);
+ }
+
+ void operator()(std::string const& text) const
+ {
+ tab(indent+tabsize);
+ std::cout << "text: \"" << text << '"' << std::endl;
+ }
+
+ int indent;
+ };
+
+ void mini_xml_printer::operator()(mini_xml const& xml) const
+ {
+ tab(indent);
+ std::cout << "tag: " << xml.name << std::endl;
+ tab(indent);
+ std::cout << '{' << std::endl;
+
+ BOOST_FOREACH(mini_xml_node const& node, xml.children)
+ {
+ boost::apply_visitor(mini_xml_node_printer(indent), node);
+ }
+
+ tab(indent);
+ std::cout << '}' << std::endl;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML grammar definition
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_xml1_grammar
+ template <typename Iterator>
+ struct mini_xml_grammar : qi::grammar<Iterator, mini_xml(), ascii::space_type>
+ {
+ mini_xml_grammar() : mini_xml_grammar::base_type(xml)
+ {
+ using qi::lit;
+ using qi::lexeme;
+ using ascii::char_;
+ using ascii::string;
+ using namespace qi::labels;
+
+ using phoenix::at_c;
+ using phoenix::push_back;
+
+ text = lexeme[+(char_ - '<') [_val += _1]];
+ node = (xml | text) [_val = _1];
+
+ start_tag =
+ '<'
+ >> !lit('/')
+ >> lexeme[+(char_ - '>') [_val += _1]]
+ >> '>'
+ ;
+
+ end_tag =
+ "</"
+ >> lit(_r1)
+ >> '>'
+ ;
+
+ xml =
+ start_tag [at_c<0>(_val) = _1]
+ >> *node [push_back(at_c<1>(_val), _1)]
+ >> end_tag(at_c<0>(_val))
+ ;
+ }
+
+ qi::rule<Iterator, mini_xml(), ascii::space_type> xml;
+ qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
+ qi::rule<Iterator, std::string(), ascii::space_type> text;
+ qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
+ qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
+ };
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string storage; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(storage));
+
+ typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar;
+ mini_xml_grammar xml; // Our grammar
+ client::mini_xml ast; // Our tree
+
+ using boost::spirit::ascii::space;
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = phrase_parse(iter, end, xml, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ client::mini_xml_printer printer;
+ printer(ast);
+ return 0;
+ }
+ else
+ {
+ std::string::const_iterator some = iter + std::min(30, int(end - iter));
+ std::string context(iter, (some>end)?end:some);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << context << "...\"\n";
+ std::cout << "-------------------------\n";
+ return 1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/mini_xml2.cpp b/src/boost/libs/spirit/example/qi/mini_xml2.cpp
new file mode 100644
index 00000000..6d56374b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml2.cpp
@@ -0,0 +1,237 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A mini XML-like parser
+//
+// [ JDG March 25, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace fusion = boost::fusion;
+ namespace phoenix = boost::phoenix;
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML tree representation
+ ///////////////////////////////////////////////////////////////////////////
+ struct mini_xml;
+
+ typedef
+ boost::variant<
+ boost::recursive_wrapper<mini_xml>
+ , std::string
+ >
+ mini_xml_node;
+
+ struct mini_xml
+ {
+ std::string name; // tag name
+ std::vector<mini_xml_node> children; // children
+ };
+}
+
+// We need to tell fusion about our mini_xml struct
+// to make it a first-class fusion citizen
+BOOST_FUSION_ADAPT_STRUCT(
+ client::mini_xml,
+ (std::string, name)
+ (std::vector<client::mini_xml_node>, children)
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Print out the mini xml tree
+ ///////////////////////////////////////////////////////////////////////////
+ int const tabsize = 4;
+
+ void tab(int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ std::cout << ' ';
+ }
+
+ struct mini_xml_printer
+ {
+ mini_xml_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const;
+
+ int indent;
+ };
+
+ struct mini_xml_node_printer : boost::static_visitor<>
+ {
+ mini_xml_node_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const
+ {
+ mini_xml_printer(indent+tabsize)(xml);
+ }
+
+ void operator()(std::string const& text) const
+ {
+ tab(indent+tabsize);
+ std::cout << "text: \"" << text << '"' << std::endl;
+ }
+
+ int indent;
+ };
+
+ void mini_xml_printer::operator()(mini_xml const& xml) const
+ {
+ tab(indent);
+ std::cout << "tag: " << xml.name << std::endl;
+ tab(indent);
+ std::cout << '{' << std::endl;
+
+ BOOST_FOREACH(mini_xml_node const& node, xml.children)
+ {
+ boost::apply_visitor(mini_xml_node_printer(indent), node);
+ }
+
+ tab(indent);
+ std::cout << '}' << std::endl;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML grammar definition
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_xml2_grammar
+ template <typename Iterator>
+ struct mini_xml_grammar
+ : qi::grammar<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type>
+ {
+ mini_xml_grammar()
+ : mini_xml_grammar::base_type(xml)
+ {
+ using qi::lit;
+ using qi::lexeme;
+ using ascii::char_;
+ using ascii::string;
+ using namespace qi::labels;
+
+ text %= lexeme[+(char_ - '<')];
+ node %= xml | text;
+
+ start_tag %=
+ '<'
+ >> !lit('/')
+ >> lexeme[+(char_ - '>')]
+ >> '>'
+ ;
+
+ end_tag =
+ "</"
+ >> lit(_r1)
+ >> '>'
+ ;
+
+ xml %=
+ start_tag[_a = _1]
+ >> *node
+ >> end_tag(_a)
+ ;
+ }
+
+ qi::rule<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type> xml;
+ qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
+ qi::rule<Iterator, std::string(), ascii::space_type> text;
+ qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
+ qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
+ };
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string storage; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(storage));
+
+ typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar;
+ mini_xml_grammar xml; // Our grammar
+ client::mini_xml ast; // Our tree
+
+ using boost::spirit::ascii::space;
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = phrase_parse(iter, end, xml, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ client::mini_xml_printer printer;
+ printer(ast);
+ return 0;
+ }
+ else
+ {
+ std::string::const_iterator some = iter + std::min(30, int(end - iter));
+ std::string context(iter, (some>end)?end:some);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << context << "...\"\n";
+ std::cout << "-------------------------\n";
+ return 1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/mini_xml3.cpp b/src/boost/libs/spirit/example/qi/mini_xml3.cpp
new file mode 100644
index 00000000..d8926c1a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml3.cpp
@@ -0,0 +1,258 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A mini XML-like parser
+//
+// [ JDG March 25, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_fusion.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+#include <boost/spirit/include/phoenix_object.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/foreach.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace fusion = boost::fusion;
+ namespace phoenix = boost::phoenix;
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML tree representation
+ ///////////////////////////////////////////////////////////////////////////
+ struct mini_xml;
+
+ typedef
+ boost::variant<
+ boost::recursive_wrapper<mini_xml>
+ , std::string
+ >
+ mini_xml_node;
+
+ struct mini_xml
+ {
+ std::string name; // tag name
+ std::vector<mini_xml_node> children; // children
+ };
+}
+
+// We need to tell fusion about our mini_xml struct
+// to make it a first-class fusion citizen
+BOOST_FUSION_ADAPT_STRUCT(
+ client::mini_xml,
+ (std::string, name)
+ (std::vector<client::mini_xml_node>, children)
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Print out the mini xml tree
+ ///////////////////////////////////////////////////////////////////////////
+ int const tabsize = 4;
+
+ void tab(int indent)
+ {
+ for (int i = 0; i < indent; ++i)
+ std::cout << ' ';
+ }
+
+ struct mini_xml_printer
+ {
+ mini_xml_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const;
+
+ int indent;
+ };
+
+ struct mini_xml_node_printer : boost::static_visitor<>
+ {
+ mini_xml_node_printer(int indent = 0)
+ : indent(indent)
+ {
+ }
+
+ void operator()(mini_xml const& xml) const
+ {
+ mini_xml_printer(indent+tabsize)(xml);
+ }
+
+ void operator()(std::string const& text) const
+ {
+ tab(indent+tabsize);
+ std::cout << "text: \"" << text << '"' << std::endl;
+ }
+
+ int indent;
+ };
+
+ void mini_xml_printer::operator()(mini_xml const& xml) const
+ {
+ tab(indent);
+ std::cout << "tag: " << xml.name << std::endl;
+ tab(indent);
+ std::cout << '{' << std::endl;
+
+ BOOST_FOREACH(mini_xml_node const& node, xml.children)
+ {
+ boost::apply_visitor(mini_xml_node_printer(indent), node);
+ }
+
+ tab(indent);
+ std::cout << '}' << std::endl;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our mini XML grammar definition
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_xml3_grammar
+ template <typename Iterator>
+ struct mini_xml_grammar
+ : qi::grammar<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type>
+ {
+ mini_xml_grammar()
+ : mini_xml_grammar::base_type(xml, "xml")
+ {
+ using qi::lit;
+ using qi::lexeme;
+ using qi::on_error;
+ using qi::fail;
+ using ascii::char_;
+ using ascii::string;
+ using namespace qi::labels;
+
+ using phoenix::construct;
+ using phoenix::val;
+
+ text %= lexeme[+(char_ - '<')];
+ node %= xml | text;
+
+ start_tag %=
+ '<'
+ >> !lit('/')
+ > lexeme[+(char_ - '>')]
+ > '>'
+ ;
+
+ end_tag =
+ "</"
+ > lit(_r1)
+ > '>'
+ ;
+
+ xml %=
+ start_tag[_a = _1]
+ > *node
+ > end_tag(_a)
+ ;
+
+ xml.name("xml");
+ node.name("node");
+ text.name("text");
+ start_tag.name("start_tag");
+ end_tag.name("end_tag");
+
+ on_error<fail>
+ (
+ xml
+ , std::cout
+ << val("Error! Expecting ")
+ << _4 // what failed?
+ << val(" here: \"")
+ << construct<std::string>(_3, _2) // iterators to error-pos, end
+ << val("\"")
+ << std::endl
+ );
+ }
+
+ qi::rule<Iterator, mini_xml(), qi::locals<std::string>, ascii::space_type> xml;
+ qi::rule<Iterator, mini_xml_node(), ascii::space_type> node;
+ qi::rule<Iterator, std::string(), ascii::space_type> text;
+ qi::rule<Iterator, std::string(), ascii::space_type> start_tag;
+ qi::rule<Iterator, void(std::string), ascii::space_type> end_tag;
+ };
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string storage; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(storage));
+
+ typedef client::mini_xml_grammar<std::string::const_iterator> mini_xml_grammar;
+ mini_xml_grammar xml; // Our grammar
+ client::mini_xml ast; // Our tree
+
+ using boost::spirit::ascii::space;
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = phrase_parse(iter, end, xml, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ client::mini_xml_printer printer;
+ printer(ast);
+ return 0;
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ return 1;
+ }
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/mini_xml_samples/1.toyxml b/src/boost/libs/spirit/example/qi/mini_xml_samples/1.toyxml
new file mode 100644
index 00000000..54181ed4
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml_samples/1.toyxml
@@ -0,0 +1 @@
+<foo></foo> \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/mini_xml_samples/2.toyxml b/src/boost/libs/spirit/example/qi/mini_xml_samples/2.toyxml
new file mode 100644
index 00000000..266e4b1f
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml_samples/2.toyxml
@@ -0,0 +1 @@
+<foo><bar></bar></foo> \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/mini_xml_samples/3.toyxml b/src/boost/libs/spirit/example/qi/mini_xml_samples/3.toyxml
new file mode 100644
index 00000000..9d89cf7b
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml_samples/3.toyxml
@@ -0,0 +1,5 @@
+<foo>
+ <bar>bar 1</bar>
+ <bar>bar 2</bar>
+ <bar>bar 3</bar>
+</foo> \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/mini_xml_samples/4.toyxml b/src/boost/libs/spirit/example/qi/mini_xml_samples/4.toyxml
new file mode 100644
index 00000000..0f220f1e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/mini_xml_samples/4.toyxml
@@ -0,0 +1 @@
+<foo><bar></foo></bar> \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/qi/nabialek.cpp b/src/boost/libs/spirit/example/qi/nabialek.cpp
new file mode 100644
index 00000000..4795578c
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/nabialek.cpp
@@ -0,0 +1,98 @@
+/*=============================================================================
+ Copyright (c) 2003 Sam Nabialek
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// The Nabialek trick.
+//
+// [ Sam Nabialek; Somewhere, sometime in 2003... ] spirit1
+// [ JDG November 17, 2009 ] spirit2
+// [ JDG January 10, 2010 ] Updated to use rule pointers
+// for efficiency.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our nabialek_trick grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct nabialek_trick : qi::grammar<
+ Iterator, ascii::space_type, qi::locals<qi::rule<Iterator, ascii::space_type>*> >
+ {
+ nabialek_trick() : nabialek_trick::base_type(start)
+ {
+ using ascii::alnum;
+ using qi::lexeme;
+ using qi::lazy;
+ using qi::_a;
+ using qi::_1;
+
+ id = lexeme[*(ascii::alnum | '_')];
+ one = id;
+ two = id >> ',' >> id;
+
+ keyword.add
+ ("one", &one)
+ ("two", &two)
+ ;
+
+ start = *(keyword[_a = _1] >> lazy(*_a));
+ }
+
+ qi::rule<Iterator, ascii::space_type> id, one, two;
+ qi::rule<Iterator, ascii::space_type, qi::locals<qi::rule<Iterator, ascii::space_type>*> > start;
+ qi::symbols<char, qi::rule<Iterator, ascii::space_type>*> keyword;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ using boost::spirit::ascii::space;
+ typedef std::string::const_iterator iterator_type;
+ typedef client::nabialek_trick<iterator_type> nabialek_trick;
+
+ nabialek_trick g; // Our grammar
+
+ std::string str = "one only\none again\ntwo first,second";
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = phrase_parse(iter, end, g, space);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/num_list1.cpp b/src/boost/libs/spirit/example/qi/num_list1.cpp
new file mode 100644
index 00000000..dc2e696d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/num_list1.cpp
@@ -0,0 +1,90 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// No actions.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist1
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using ascii::space;
+
+ bool r = phrase_parse(
+ first, /*< start iterator >*/
+ last, /*< end iterator >*/
+ double_ >> *(',' >> double_), /*< the parser >*/
+ space /*< the skip-parser >*/
+ );
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ if (client::parse_numbers(str.begin(), str.end()))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/num_list2.cpp b/src/boost/libs/spirit/example/qi/num_list2.cpp
new file mode 100644
index 00000000..9fb854e7
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/num_list2.cpp
@@ -0,0 +1,109 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// The numbers are inserted in a vector using phoenix.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace phoenix = boost::phoenix;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist2
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using qi::_1;
+ using ascii::space;
+ using phoenix::push_back;
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[push_back(phoenix::ref(v), _1)]
+ >> *(',' >> double_[push_back(phoenix::ref(v), _1)])
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/num_list3.cpp b/src/boost/libs/spirit/example/qi/num_list3.cpp
new file mode 100644
index 00000000..3ba09ffb
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/num_list3.cpp
@@ -0,0 +1,108 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// The numbers are inserted in a vector using phoenix.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace phoenix = boost::phoenix;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist3
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using qi::_1;
+ using ascii::space;
+ using phoenix::push_back;
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[push_back(phoenix::ref(v), _1)] % ','
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/num_list4.cpp b/src/boost/libs/spirit/example/qi/num_list4.cpp
new file mode 100644
index 00000000..552dd8d1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/num_list4.cpp
@@ -0,0 +1,106 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// The numbers are inserted in a vector using phoenix.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/spirit/include/phoenix_stl.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist4
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using qi::double_;
+ using qi::phrase_parse;
+ using qi::_1;
+ using ascii::space;
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_ % ','
+ )
+ ,
+ // End grammar
+
+ space, v);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/parse_date.cpp b/src/boost/libs/spirit/example/qi/parse_date.cpp
new file mode 100644
index 00000000..82b5092d
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/parse_date.cpp
@@ -0,0 +1,125 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Hartmut Kaiser
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+// This example is not meant to be a sophisticated date parser. It's sole
+// purpose is to demonstrate the intrinsic attribute transformation
+// capabilities of a rule.
+//
+// Note how the rule exposes a fusion sequence, but gets passed an instance of
+// a boost::gregorian::date as the attribute. In order to make these types
+// compatible for the rule we define a specialization of the customization
+// point called 'transform_attribute'.
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/vector.hpp>
+#include <boost/date_time.hpp>
+
+// define custom transformation
+namespace boost { namespace spirit { namespace traits
+{
+ // This specialization of the customization point transform_attribute
+ // allows to pass a boost::gregorian::date to a rule which is expecting
+ // a fusion sequence consisting out of three integers as its attribute.
+ template<>
+ struct transform_attribute<
+ boost::gregorian::date, fusion::vector<int, int, int>, qi::domain>
+ {
+ typedef fusion::vector<int, int, int> date_parts;
+
+ // The embedded typedef 'type' exposes the attribute as it will be
+ // passed to the right hand side of the rule.
+ typedef date_parts type;
+
+ // The function pre() is called for down-stream conversion of the
+ // attribute supplied to the rule to the attribute expected by the
+ // right hand side.
+ // The supplied attribute might have been pre-initialized by parsers
+ // (i.e. semantic actions) higher up the parser hierarchy (in the
+ // grammar), in which case we would need to properly initialize the
+ // returned value from the argument. In this example this is not
+ // required, so we just create a new instance of a date_parts.
+ static date_parts pre(boost::gregorian::date)
+ {
+ return date_parts();
+ }
+
+ // The function post() is called for up-stream conversion of the
+ // results returned from parsing the right hand side of the rule.
+ // We need to initialize the attribute supplied to the rule (referenced
+ // by the first argument) with the values taken from the parsing
+ // results (referenced by the second argument).
+ static void post(boost::gregorian::date& d, date_parts const& v)
+ {
+ d = boost::gregorian::date(fusion::at_c<0>(v), fusion::at_c<1>(v)
+ , fusion::at_c<2>(v));
+ }
+
+ // The function fail() is called whenever the parsing of the right hand
+ // side of the rule fails. We don't need to do anything here.
+ static void fail(boost::gregorian::date&) {}
+ };
+}}}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ template <typename Iterator>
+ bool parse_date(Iterator& first, Iterator last, boost::gregorian::date& d)
+ {
+ typedef boost::fusion::vector<int, int, int> date_parts;
+ qi::rule<Iterator, date_parts(), qi::space_type> date =
+ qi::int_ >> '-' >> qi::int_ >> '-' >> qi::int_;
+
+ return phrase_parse(first, last, date, qi::space, d);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA date parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a date of the form : year-month-day\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ boost::gregorian::date d;
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = client::parse_date(iter, end, d);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << d << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/porting_guide_classic.cpp b/src/boost/libs/spirit/example/qi/porting_guide_classic.cpp
new file mode 100644
index 00000000..b12f0f22
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/porting_guide_classic.cpp
@@ -0,0 +1,108 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+//[porting_guide_classic_includes
+#include <boost/spirit/include/classic.hpp>
+#include <boost/spirit/include/phoenix1.hpp>
+#include <iostream>
+#include <string>
+//]
+
+//[porting_guide_classic_namespace
+using namespace boost::spirit::classic;
+//]
+
+//[porting_guide_classic_grammar
+struct roman : public grammar<roman>
+{
+ template <typename ScannerT>
+ struct definition
+ {
+ definition(roman const& self)
+ {
+ hundreds.add
+ ("C" , 100)("CC" , 200)("CCC" , 300)("CD" , 400)("D" , 500)
+ ("DC" , 600)("DCC" , 700)("DCCC" , 800)("CM" , 900) ;
+
+ tens.add
+ ("X" , 10)("XX" , 20)("XXX" , 30)("XL" , 40)("L" , 50)
+ ("LX" , 60)("LXX" , 70)("LXXX" , 80)("XC" , 90) ;
+
+ ones.add
+ ("I" , 1)("II" , 2)("III" , 3)("IV" , 4)("V" , 5)
+ ("VI" , 6)("VII" , 7)("VIII" , 8)("IX" , 9) ;
+
+ first = eps_p [phoenix::var(self.r) = phoenix::val(0)]
+ >> ( +ch_p('M') [phoenix::var(self.r) += phoenix::val(1000)]
+ || hundreds [phoenix::var(self.r) += phoenix::_1]
+ || tens [phoenix::var(self.r) += phoenix::_1]
+ || ones [phoenix::var(self.r) += phoenix::_1]
+ ) ;
+ }
+
+ rule<ScannerT> first;
+ symbols<unsigned> hundreds;
+ symbols<unsigned> tens;
+ symbols<unsigned> ones;
+
+ rule<ScannerT> const& start() const { return first; }
+ };
+
+ roman(unsigned& r_) : r(r_) {}
+ unsigned& r;
+};
+//]
+
+int main()
+{
+ {
+ //[porting_guide_classic_parse
+ std::string input("1,1");
+ parse_info<std::string::iterator> pi = parse(input.begin(), input.end(), int_p);
+
+ if (pi.hit)
+ std::cout << "successful match!\n";
+
+ if (pi.full)
+ std::cout << "full match!\n";
+ else
+ std::cout << "stopped at: " << std::string(pi.stop, input.end()) << "\n";
+
+ std::cout << "matched length: " << pi.length << "\n";
+ //]
+ }
+
+ {
+ //[porting_guide_classic_phrase_parse
+ std::string input(" 1, 1");
+ parse_info<std::string::iterator> pi = parse(input.begin(), input.end(), int_p, space_p);
+
+ if (pi.hit)
+ std::cout << "successful match!\n";
+
+ if (pi.full)
+ std::cout << "full match!\n";
+ else
+ std::cout << "stopped at: " << std::string(pi.stop, input.end()) << "\n";
+
+ std::cout << "matched length: " << pi.length << "\n";
+ //]
+ }
+
+ {
+ //[porting_guide_classic_use_grammar
+ std::string input("MMIX"); // MMIX == 2009
+ unsigned value = 0;
+ roman r(value);
+ parse_info<std::string::iterator> pi = parse(input.begin(), input.end(), r);
+ if (pi.hit)
+ std::cout << "successfully matched: " << value << "\n";
+ //]
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/porting_guide_qi.cpp b/src/boost/libs/spirit/example/qi/porting_guide_qi.cpp
new file mode 100644
index 00000000..d1ec0335
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/porting_guide_qi.cpp
@@ -0,0 +1,106 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+//[porting_guide_qi_includes
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <iostream>
+#include <string>
+#include <algorithm>
+//]
+
+//[porting_guide_qi_namespace
+using namespace boost::spirit;
+//]
+
+//[porting_guide_qi_grammar
+template <typename Iterator>
+struct roman : qi::grammar<Iterator, unsigned()>
+{
+ roman() : roman::base_type(first)
+ {
+ hundreds.add
+ ("C" , 100)("CC" , 200)("CCC" , 300)("CD" , 400)("D" , 500)
+ ("DC" , 600)("DCC" , 700)("DCCC" , 800)("CM" , 900) ;
+
+ tens.add
+ ("X" , 10)("XX" , 20)("XXX" , 30)("XL" , 40)("L" , 50)
+ ("LX" , 60)("LXX" , 70)("LXXX" , 80)("XC" , 90) ;
+
+ ones.add
+ ("I" , 1)("II" , 2)("III" , 3)("IV" , 4)("V" , 5)
+ ("VI" , 6)("VII" , 7)("VIII" , 8)("IX" , 9) ;
+
+ // qi::_val refers to the attribute of the rule on the left hand side
+ first = eps [qi::_val = 0]
+ >> ( +lit('M') [qi::_val += 1000]
+ || hundreds [qi::_val += qi::_1]
+ || tens [qi::_val += qi::_1]
+ || ones [qi::_val += qi::_1]
+ ) ;
+ }
+
+ qi::rule<Iterator, unsigned()> first;
+ qi::symbols<char, unsigned> hundreds;
+ qi::symbols<char, unsigned> tens;
+ qi::symbols<char, unsigned> ones;
+};
+//]
+
+int main()
+{
+ {
+ //[porting_guide_qi_parse
+ std::string input("1,1");
+ std::string::iterator it = input.begin();
+ bool result = qi::parse(it, input.end(), qi::int_);
+
+ if (result)
+ std::cout << "successful match!\n";
+
+ if (it == input.end())
+ std::cout << "full match!\n";
+ else
+ std::cout << "stopped at: " << std::string(it, input.end()) << "\n";
+
+ // seldomly needed: use std::distance to calculate the length of the match
+ std::cout << "matched length: " << std::distance(input.begin(), it) << "\n";
+ //]
+ }
+
+ {
+ //[porting_guide_qi_phrase_parse
+ std::string input(" 1, 1");
+ std::string::iterator it = input.begin();
+ bool result = qi::phrase_parse(it, input.end(), qi::int_, ascii::space);
+
+ if (result)
+ std::cout << "successful match!\n";
+
+ if (it == input.end())
+ std::cout << "full match!\n";
+ else
+ std::cout << "stopped at: " << std::string(it, input.end()) << "\n";
+
+ // seldomly needed: use std::distance to calculate the length of the match
+ std::cout << "matched length: " << std::distance(input.begin(), it) << "\n";
+ //]
+ }
+
+ {
+ //[porting_guide_qi_use_grammar
+ std::string input("MMIX"); // MMIX == 2009
+ std::string::iterator it = input.begin();
+ unsigned value = 0;
+ roman<std::string::iterator> r;
+ if (qi::parse(it, input.end(), r, value))
+ std::cout << "successfully matched: " << value << "\n";
+ //]
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/reference.cpp b/src/boost/libs/spirit/example/qi/reference.cpp
new file mode 100644
index 00000000..4cd8a147
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/reference.cpp
@@ -0,0 +1,1481 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ http://spirit.sourceforge.net/
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+// this code is not supposed to be executed, so the asserts are for
+// demonstration purposes only
+// boostinspect:naassert_macro
+
+//[reference_includes
+#include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/assert.hpp>
+#include <boost/predef/other/endian.h>
+#include <iostream>
+#include <string>
+#include <cstdlib>
+//]
+
+//[reference_test
+template <typename P>
+void test_parser(
+ char const* input, P const& p, bool full_match = true)
+{
+ using boost::spirit::qi::parse;
+
+ char const* f(input);
+ char const* l(f + strlen(f));
+ if (parse(f, l, p) && (!full_match || (f == l)))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+
+template <typename P>
+void test_phrase_parser(
+ char const* input, P const& p, bool full_match = true)
+{
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::qi::ascii::space;
+
+ char const* f(input);
+ char const* l(f + strlen(f));
+ if (phrase_parse(f, l, p, space) && (!full_match || (f == l)))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_test_attr
+template <typename P, typename T>
+void test_parser_attr(
+ char const* input, P const& p, T& attr, bool full_match = true)
+{
+ using boost::spirit::qi::parse;
+
+ char const* f(input);
+ char const* l(f + strlen(f));
+ if (parse(f, l, p, attr) && (!full_match || (f == l)))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+
+template <typename P, typename T>
+void test_phrase_parser_attr(
+ char const* input, P const& p, T& attr, bool full_match = true)
+{
+ using boost::spirit::qi::phrase_parse;
+ using boost::spirit::qi::ascii::space;
+
+ char const* f(input);
+ char const* l(f + strlen(f));
+ if (phrase_parse(f, l, p, space, attr) && (!full_match || (f == l)))
+ std::cout << "ok" << std::endl;
+ else
+ std::cout << "fail" << std::endl;
+}
+//]
+
+//[reference_print_info
+struct printer
+{
+ typedef boost::spirit::utf8_string string;
+
+ void element(string const& tag, string const& value, int depth) const
+ {
+ for (int i = 0; i < (depth*4); ++i) // indent to depth
+ std::cout << ' ';
+
+ std::cout << "tag: " << tag;
+ if (value != "")
+ std::cout << ", value: " << value;
+ std::cout << std::endl;
+ }
+};
+
+void print_info(boost::spirit::info const& what)
+{
+ using boost::spirit::basic_info_walker;
+
+ printer pr;
+ basic_info_walker<printer> walker(pr, what.tag, 0);
+ boost::apply_visitor(walker, what.value);
+}
+//]
+
+//[reference_test_real_policy
+///////////////////////////////////////////////////////////////////////////////
+// These policies can be used to parse thousand separated
+// numbers with at most 2 decimal digits after the decimal
+// point. e.g. 123,456,789.01
+///////////////////////////////////////////////////////////////////////////////
+template <typename T>
+struct ts_real_policies : boost::spirit::qi::ureal_policies<T>
+{
+ // 2 decimal places Max
+ template <typename Iterator, typename Attribute>
+ static bool
+ parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr,
+ int& frac_digits)
+ {
+ Iterator savef = first;
+ bool r = boost::spirit::qi::
+ extract_uint<T, 10, 1, 2, true>::call(first, last, attr);
+ if (r) {
+ // Optimization note: don't compute frac_digits if T is
+ // an unused_type. This should be optimized away by the compiler.
+ if (!boost::is_same<T, boost::spirit::unused_type>::value)
+ frac_digits = static_cast<int>(std::distance(savef, first));
+ }
+ return r;
+ }
+
+ // No exponent
+ template <typename Iterator>
+ static bool
+ parse_exp(Iterator&, Iterator const&)
+ {
+ return false;
+ }
+
+ // No exponent
+ template <typename Iterator, typename Attribute>
+ static bool
+ parse_exp_n(Iterator&, Iterator const&, Attribute&)
+ {
+ return false;
+ }
+
+ // Thousands separated numbers
+ template <typename Iterator, typename Accumulator>
+ static bool
+ parse_n(Iterator& first, Iterator const& last, Accumulator& result)
+ {
+ using boost::spirit::qi::uint_parser;
+ namespace qi = boost::spirit::qi;
+
+ uint_parser<unsigned, 10, 1, 3> uint3;
+ uint_parser<unsigned, 10, 3, 3> uint3_3;
+
+ if (parse(first, last, uint3, result))
+ {
+ Accumulator n;
+ Iterator iter = first;
+
+ while (qi::parse(iter, last, ',') && qi::parse(iter, last, uint3_3, n))
+ {
+ result = result * 1000 + n;
+ first = iter;
+ }
+
+ return true;
+ }
+ return false;
+ }
+};
+//]
+
+//[reference_test_bool_policy
+///////////////////////////////////////////////////////////////////////////////
+// These policies can be used to parse "eurt" (i.e. "true" spelled backwards)
+// as `false`
+///////////////////////////////////////////////////////////////////////////////
+struct backwards_bool_policies : boost::spirit::qi::bool_policies<>
+{
+ // we want to interpret a 'true' spelled backwards as 'false'
+ template <typename Iterator, typename Attribute>
+ static bool
+ parse_false(Iterator& first, Iterator const& last, Attribute& attr)
+ {
+ namespace qi = boost::spirit::qi;
+ if (qi::detail::string_parse("eurt", first, last, qi::unused))
+ {
+ namespace traits = boost::spirit::traits;
+ traits::assign_to(false, attr); // result is false
+ return true;
+ }
+ return false;
+ }
+};
+//]
+
+//[reference_qi_complex
+// a simple complex number representation z = a + bi
+struct complex
+{
+ complex (double a = 0.0, double b = 0.0)
+ : a(a), b(b)
+ {}
+
+ double a;
+ double b;
+};
+//]
+
+//[reference_qi_stream_complex
+// define streaming operator for the type complex
+std::istream&
+operator>> (std::istream& is, complex& z)
+{
+ char lbrace = '\0', comma = '\0', rbrace = '\0';
+ is >> lbrace >> z.a >> comma >> z.b >> rbrace;
+ if (lbrace != '{' || comma != ',' || rbrace != '}')
+ is.setstate(std::ios_base::failbit);
+ return is;
+}
+//]
+
+//[reference_qi_auto_complex
+/*`The following construct is required to allow the `complex` data structure
+ to be utilized as a __fusion__ sequence. This is required as we will
+ emit output for this data structure with a __qi__ sequence:
+ `'{' >> qi::double_ >> ',' >> qi::double_ >> '}'`.
+*/
+BOOST_FUSION_ADAPT_STRUCT(
+ complex,
+ (double, a)
+ (double, b)
+)
+
+/*`We add a specialization for the create_parser customization point
+ defining a custom output format for the complex type. Generally, any
+ specialization for create_parser is expected to return the proto
+ expression to be used to match input for the type the customization
+ point has been specialized for.
+ */
+/*`We need to utilize `proto::deep_copy` as the expression contains literals
+ (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto
+ expression by reference only. The deep copy converts the proto tree to
+ hold this by value. The deep copy operation can be left out for simpler
+ proto expressions (not containing references to temporaries). Alternatively
+ you could use the `proto::make_expr` facility to build the required
+ proto expression.
+*/
+namespace boost { namespace spirit { namespace traits
+{
+ template <>
+ struct create_parser<complex>
+ {
+ typedef proto::result_of::deep_copy<
+ BOOST_TYPEOF('{' >> qi::double_ >> ',' >> qi::double_ >> '}')
+ >::type type;
+
+ static type call()
+ {
+ return proto::deep_copy(
+ '{' >> qi::double_ >> ',' >> qi::double_ >> '}');
+ }
+ };
+}}}
+//]
+
+//[reference_qi_auxiliary_attr_cast_data1
+// this is just a test structure we want to use in place of an int
+struct int_data
+{
+ int i;
+};
+
+
+// we provide a custom attribute transformation to allow its use as an int
+namespace boost { namespace spirit { namespace traits
+{
+ // in this case we just expose the embedded 'int' as the attribute instance
+ // to use, allowing to leave the function 'post()' empty
+ template <>
+ struct transform_attribute<int_data, int, qi::domain>
+ {
+ typedef int& type;
+ static int& pre(int_data& d) { return d.i; }
+ static void post(int_data& val, int const& attr) {}
+ static void fail(int_data&) {}
+ };
+}}}
+//]
+
+namespace client
+{
+ using boost::spirit::qi::grammar;
+ using boost::spirit::qi::rule;
+ using boost::spirit::ascii::space_type;
+
+//[reference_grammar_definition
+/*`Basic grammar usage:
+ */
+ struct num_list : grammar<char const*, space_type>
+ {
+ num_list() : base_type(start)
+ {
+ using boost::spirit::int_;
+ num = int_;
+ start = num >> *(',' >> num);
+ }
+
+ rule<char const*, space_type> start, num;
+ };
+//]
+}
+
+int
+main()
+{
+ {
+ //[reference_using_declarations_lit_char
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::char_;
+ //]
+
+ //[reference_char_literals
+ test_parser("x", 'x'); // plain literal
+ test_parser("x", lit('x')); // explicit literal
+ test_parser("x", char_('x')); // ascii::char_
+ //]
+
+ //[reference_char_range
+ char ch;
+ test_parser_attr("5", char_('0','9'), ch); // ascii::char_ range
+ std::cout << ch << std::endl; // prints '5'
+ //]
+
+ //[reference_char_set
+ test_parser_attr("5", char_("0-9"), ch); // ascii::char_ set
+ std::cout << ch << std::endl; // prints '5'
+ //]
+
+ //[reference_char_phoenix
+ namespace phx = boost::phoenix;
+ test_parser("x", phx::val('x')); // direct
+ test_parser("5",
+ char_(phx::val('0'),phx::val('9'))); // ascii::char_ range
+ //]
+ }
+
+ {
+ //[reference_using_declarations_lit_string
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::string;
+ //]
+
+ //[reference_string_literals
+ test_parser("boost", "boost"); // plain literal
+ test_parser("boost", lit("boost")); // explicit literal
+ test_parser("boost", string("boost")); // ascii::string
+ //]
+ }
+
+ {
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::string;
+
+ //[reference_string_std_string
+ std::string s("boost");
+ test_parser("boost", s); // direct
+ test_parser("boost", lit(s)); // explicit
+ test_parser("boost", string(s)); // ascii::string
+ //]
+ }
+
+ {
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::string;
+
+ //[reference_string_phoenix
+ namespace phx = boost::phoenix;
+ test_parser("boost", phx::val("boost")); // direct
+ test_parser("boost", lit(phx::val("boost"))); // explicit
+ test_parser("boost", string(phx::val("boost"))); // ascii::string
+ //]
+ }
+
+ {
+ //[reference_using_declarations_symbols
+ using boost::spirit::qi::symbols;
+ //]
+
+ //[reference_symbols_with_data
+ symbols<char, int> sym;
+
+ sym.add
+ ("Apple", 1)
+ ("Banana", 2)
+ ("Orange", 3)
+ ;
+
+ int i;
+ test_parser_attr("Banana", sym, i);
+ std::cout << i << std::endl;
+ //]
+ }
+
+ {
+ //[reference_using_declarations_lexeme
+ using boost::spirit::qi::lexeme;
+ using boost::spirit::qi::lit;
+ using boost::spirit::ascii::digit;
+ //]
+
+ //[reference_lexeme
+ /*`The use of lexeme here will prevent skipping in between the
+ digits and the sign making inputs such as `"1 2 345"` erroneous.*/
+ test_phrase_parser("12345", lexeme[ -(lit('+') | '-') >> +digit ]);
+ //]
+ }
+
+ // as
+ {
+ //[reference_using_declarations_as
+ using boost::spirit::utree;
+ using boost::spirit::utree_type;
+ using boost::spirit::utf8_symbol_type;
+ using boost::spirit::qi::as;
+ using boost::spirit::qi::as_string;
+ using boost::spirit::qi::char_;
+ //]
+
+ //[reference_as
+ /*`To properly handle string concatenation with __utree__, we
+ make use of `as_string[]`. We also use `as<T>` to explicitly create
+ a __utree__ symbol node.*/
+ utree ut;
+
+ typedef as<utf8_symbol_type> as_symbol_type;
+ as_symbol_type const as_symbol = as_symbol_type();
+
+ test_parser_attr("foo", as_string[*char_], ut);
+ std::cout << ut << std::endl; // will output >"foo"<
+ BOOST_ASSERT(ut.which() == utree_type::string_type);
+ ut.clear();
+
+ test_parser_attr("foo", as<std::string>()[*char_], ut);
+ std::cout << ut << std::endl; // will output >"foo"<
+ BOOST_ASSERT(ut.which() == utree_type::string_type);
+ ut.clear();
+
+ test_parser_attr("foo", as_symbol[*char_], ut);
+ std::cout << ut << std::endl; // will output >foo<
+ BOOST_ASSERT(ut.which() == utree_type::symbol_type);
+ ut.clear();
+
+ test_parser_attr("foo", as<utf8_symbol_type>()[*char_], ut);
+ std::cout << ut << std::endl; // will output >foo<
+ BOOST_ASSERT(ut.which() == utree_type::symbol_type);
+ //]
+ }
+
+ {
+ //[reference_using_declarations_no_skip
+ using boost::spirit::qi::no_skip;
+ using boost::spirit::qi::char_;
+ //]
+
+ //[reference_no_skip
+ /*`The use of no_skip here will prevent skipping of whitespace in front
+ and in between the characters of the string `' abc '`.*/
+
+ std::string str;
+ test_phrase_parser_attr("' abc '",
+ '\'' >> no_skip[+~char_('\'')] >> '\'', str);
+ std::cout << str << std::endl; // will output: > abc <
+ //]
+ }
+
+ {
+ //[reference_using_declarations_hold
+ using boost::spirit::qi::hold;
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::attr;
+ //]
+
+ //[reference_hold
+ /*`The use of `hold[]` here will make sure the changes to the attribute
+ caused by the (failing) first alternative will not be visible after
+ the whole parsing succeeded. */
+
+ std::vector<int> v;
+ test_phrase_parser_attr("123",
+ hold[int_ >> ':' >> int_] | int_ >> attr(0), v);
+ std::cout << v[0] << "," << v[1] << std::endl; // will output: >123,0<
+ //]
+ }
+
+ {
+ //[reference_using_declarations_no_case
+ using boost::spirit::ascii::no_case;
+ using boost::spirit::ascii::char_;
+ using boost::spirit::ascii::alnum;
+ using boost::spirit::qi::symbols;
+ //]
+
+ //[reference_no_case
+ test_parser("X", no_case[char_('x')]);
+ test_parser("6", no_case[alnum]);
+ //]
+
+ //[reference_symbols_with_no_case
+ symbols<char, int> sym;
+
+ sym.add
+ ("apple", 1) // symbol strings are added in lowercase...
+ ("banana", 2)
+ ("orange", 3)
+ ;
+
+ int i;
+ // ...because sym is used for case-insensitive parsing
+ test_parser_attr("Apple", no_case[ sym ], i);
+ std::cout << i << std::endl;
+ test_parser_attr("ORANGE", no_case[ sym ], i);
+ std::cout << i << std::endl;
+ //]
+ }
+
+ {
+ //[reference_using_declarations_omit
+ using boost::spirit::qi::omit;
+ using boost::spirit::qi::int_;
+ using boost::spirit::ascii::char_;
+ //]
+
+ //[reference_omit
+ /*`This parser ignores the first two characters
+ and extracts the succeeding `int`:*/
+ int i;
+ test_parser_attr("xx345", omit[char_ >> char_] >> int_, i);
+ std::cout << i << std::endl; // should print 345
+ //]
+ }
+
+ {
+ //[reference_using_declarations_matches
+ using boost::spirit::qi::matches;
+ using boost::spirit::qi::int_;
+ //]
+
+ //[reference_matches
+ /*`This parser tries to match an `int` and returns `true` a its
+ attribute as it succeeded matching: */
+ bool result = false;
+ test_parser_attr("345", matches[int_], result);
+ std::cout << std::boolalpha << result << std::endl; // should print: true
+
+ /*`This parser tries to match an `int` as well and returns `false` as
+ its attribute as it fails matching: */
+ result = true;
+ test_parser_attr("abc", matches[int_], result);
+ std::cout << std::boolalpha << result << std::endl; // should print: false
+ //]
+ }
+
+ {
+ //[reference_using_declarations_raw
+ using boost::spirit::qi::raw;
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::ascii::alnum;
+ //]
+
+ //[reference_raw
+ //`This parser matches and extracts C++ identifiers:
+ std::string id;
+ test_parser_attr("James007", raw[(alpha | '_') >> *(alnum | '_')], id);
+ std::cout << id << std::endl; // should print James007
+ //]
+ }
+
+ {
+ //[reference_using_declarations_repeat
+ using boost::spirit::qi::repeat;
+ using boost::spirit::qi::lit;
+ using boost::spirit::qi::uint_parser;
+ using boost::spirit::qi::_1;
+ using boost::spirit::ascii::char_;
+ namespace phx = boost::phoenix;
+ //]
+
+ //[reference_repeat
+ //`A parser for a file name with a maximum of 255 characters:
+ test_parser("batman.jpeg", repeat(1, 255)[char_("a-zA-Z_./")]);
+
+ /*`A parser for a specific bitmap file format which has exactly 4096 RGB color information.
+ (for the purpose of this example, we will be testing only 3 RGB color information.)
+ */
+ uint_parser<unsigned, 16, 6, 6> rgb;
+ std::vector<unsigned> colors;
+ test_parser_attr("ffffff0000003f3f3f", repeat(3)[rgb], colors);
+ std::cout
+ << std::hex
+ << colors[0] << ','
+ << colors[1] << ','
+ << colors[2] << std::endl;
+
+ /*`A 256 bit binary string (1..256 1s or 0s). (For the purpose of this example,
+ we will be testing only 16 bits.)
+ */
+ test_parser("1011101011110010", repeat(16)[lit('1') | '0']);
+ //]
+
+ std::cout << std::dec; // reset to decimal
+
+ //[reference_repeat_pascal
+ /*`This trivial example cannot be practically defined in traditional EBNF.
+ Although some EBNF variants allow more powerful repetition constructs other
+ than the Kleene Star, we are still limited to parsing fixed strings.
+ The nature of EBNF forces the repetition factor to be a constant.
+ On the other hand, Spirit allows the repetition factor to be variable at
+ run time. We could write a grammar that accepts the input string above.
+ Example using phoenix:
+ */
+ std::string str;
+ int n;
+ test_parser_attr("\x0bHello World",
+ char_[phx::ref(n) = _1] >> repeat(phx::ref(n))[char_], str);
+ std::cout << n << ',' << str << std::endl; // will print "11,Hello World"
+ //]
+ }
+
+ {
+ //[reference_using_declarations_skip
+ using boost::spirit::qi::skip;
+ using boost::spirit::qi::int_;
+ using boost::spirit::ascii::space;
+ //]
+
+ //[reference_skip
+ /*`Explicitly specify a skip parser. This parser parses comma
+ delimited numbers, ignoring spaces.*/
+ test_parser("1, 2, 3, 4, 5", skip(space)[int_ >> *(',' >> int_)]);
+ //]
+ }
+
+ // attr()
+ {
+ //[reference_using_declarations_attr
+ namespace phx = boost::phoenix;
+ using boost::spirit::qi::attr;
+ //]
+
+ //[reference_attr
+ std::string str;
+ test_parser_attr("", attr("boost"), str);
+ std::cout << str << std::endl; // will print 'boost'
+
+ double d;
+ test_parser_attr("", attr(1.0), d);
+ std::cout << d << std::endl; // will print '1.0'
+ //]
+
+ //[reference_attr_phoenix
+ d = 0.0;
+ double d1 = 1.2;
+ test_parser_attr("", attr(phx::ref(d1)), d);
+ std::cout << d << std::endl; // will print '1.2'
+ //]
+ }
+
+ // attr_cast
+ {
+ //[reference_qi_using_declarations_attr_cast
+ using boost::spirit::qi::int_;
+ //]
+
+ //[reference_qi_attr_cast1
+ int_data d = { 0 };
+ test_parser_attr("1", boost::spirit::qi::attr_cast(int_), d);
+ std::cout << d.i << std::endl;
+ //]
+ }
+
+ // eol
+ {
+ //[reference_using_declarations_eol
+ using boost::spirit::qi::eol;
+ //]
+
+ //[reference_eol
+ test_parser("\n", eol);
+ //]
+ }
+
+ // eoi
+ {
+ //[reference_using_declarations_eoi
+ using boost::spirit::qi::eoi;
+ //]
+
+ //[reference_eoi
+ test_parser("", eoi);
+ //]
+ }
+
+ // eps
+ {
+ //[reference_using_declarations_eps
+ using boost::spirit::qi::eps;
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::_1;
+ namespace phx = boost::phoenix;
+ //]
+
+ //[reference_eps
+ //`Basic `eps`:
+ test_parser("", eps); // always matches
+ //]
+
+ //[reference_eps_if
+ /*`This example simulates the "classic" `if_p` parser. Here, `int_` will be
+ tried only if the condition, `c`, is true.
+ */
+ bool c = true; // a flag
+ test_parser("1234", eps(phx::ref(c) == true) >> int_);
+ //]
+
+ //[reference_eps_while
+ /*`This example simulates the "classic" `while_p` parser. Here, the kleene loop
+ will exit once the condition, `c`, becomes true. Notice that the condition, `c`,
+ is turned to `false` when we get to parse `4`.
+ */
+ test_phrase_parser("1 2 3 4",
+ *(eps(phx::ref(c) == true) >> int_[phx::ref(c) = (_1 == 4)]));
+ //]
+ }
+
+ // lazy
+ {
+ //[reference_using_declarations_lazy
+ using boost::spirit::qi::lazy;
+ using boost::spirit::ascii::string;
+ using boost::phoenix::val;
+ //]
+
+ //[reference_lazy
+ /*` Here, the phoenix::val expression creates a function
+ that returns its argument when invoked. The lazy expression
+ defers the invocation of this function at parse time. Then,
+ this parser (string parser) is called into action. All this
+ takes place at parse time.
+ */
+ test_parser("Hello", lazy(val(string("Hello"))));
+
+ //` The above is equivalent to:
+ test_parser("Hello", string("Hello"));
+ //]
+ }
+
+ // char class
+ {
+ //[reference_using_declarations_char_class
+ using boost::spirit::ascii::alnum;
+ using boost::spirit::ascii::blank;
+ using boost::spirit::ascii::digit;
+ using boost::spirit::ascii::lower;
+ //]
+
+ //[reference_char_class
+ test_parser("1", alnum);
+ test_parser(" ", blank);
+ test_parser("1", digit);
+ test_parser("a", lower);
+ //]
+ }
+
+ // uint
+ {
+ //[reference_using_declarations_uint
+ using boost::phoenix::val;
+ using boost::spirit::qi::lit;
+ using boost::spirit::qi::uint_;
+ using boost::spirit::qi::uint_parser;
+ //]
+
+ //[reference_uint
+ // unsigned int
+ test_parser("12345", uint_);
+ test_parser("12345", uint_(12345));
+ test_parser("12345", uint_(val(12345)));
+
+ // literals
+ test_parser("12345", lit(12345));
+ test_parser("12345", lit(val(12345)));
+ //]
+
+ //[reference_thousand_separated
+ //`Thousand separated number parser:
+ uint_parser<unsigned, 10, 1, 3> uint3_p; // 1..3 digits
+ uint_parser<unsigned, 10, 3, 3> uint3_3_p; // exactly 3 digits
+ test_parser("12,345,678", uint3_p >> *(',' >> uint3_3_p));
+ //]
+ }
+
+ // int
+ {
+ //[reference_using_declarations_int
+ using boost::phoenix::val;
+ using boost::spirit::qi::lit;
+ using boost::spirit::qi::int_;
+ //]
+
+ //[reference_int
+ // signed int
+ test_parser("+12345", int_);
+ test_parser("-12345", int_);
+ test_parser("+12345", int_(12345));
+ test_parser("-12345", int_(-12345));
+ test_parser("+12345", int_(val(12345)));
+ test_parser("-12345", int_(val(-12345)));
+
+ // literals
+ test_parser("+12345", lit(12345));
+ test_parser("-12345", lit(-12345));
+ test_parser("+12345", lit(val(12345)));
+ test_parser("-12345", lit(val(-12345)));
+ //]
+ }
+
+ // real
+ {
+ //[reference_using_declarations_real
+ using boost::phoenix::val;
+ using boost::spirit::qi::double_;
+ using boost::spirit::qi::real_parser;
+ using boost::spirit::qi::lit;
+ //]
+
+ //[reference_real
+ // double
+ test_parser("+12345e6", double_);
+ test_parser("-12345e6", double_);
+ test_parser("+12345e6", double_(12345e6));
+ test_parser("-12345e6", double_(-123456e6));
+ test_parser("+12345e6", double_(val(12345e6)));
+ test_parser("-12345e6", double_(val(-123456e6)));
+
+ // literals
+ test_parser("+12345e6", lit(12345e6));
+ test_parser("-12345e6", lit(-123456e6));
+ test_parser("+12345e6", lit(val(12345e6)));
+ test_parser("-12345e6", lit(val(-123456e6)));
+ //]
+
+ //[reference_custom_real
+ real_parser<double, ts_real_policies<double> > ts_real;
+ test_parser("123,456,789.01", ts_real);
+ test_parser("123,456,789.01", ts_real(123456789.01));
+ //]
+ }
+
+ // bool_
+ {
+ //[reference_using_declarations_bool
+ using boost::phoenix::val;
+ using boost::spirit::qi::bool_;
+ using boost::spirit::qi::bool_parser;
+ using boost::spirit::qi::lit;
+ //]
+
+ //[reference_bool
+ // bool
+ test_parser("true", bool_);
+ test_parser("false", bool_);
+ test_parser("true", bool_(true));
+ test_parser("false", bool_(false));
+ test_parser("true", bool_(val(true)));
+ test_parser("false", bool_(val(false)));
+
+ // literals
+ test_parser("true", lit(true));
+ test_parser("false", lit(false));
+ test_parser("true", lit(val(true)));
+ test_parser("false", lit(val(false)));
+ //]
+
+ //[reference_custom_bool
+ bool_parser<bool, backwards_bool_policies> backwards_bool;
+ test_parser("true", backwards_bool);
+ test_parser("eurt", backwards_bool);
+ test_parser("true", backwards_bool(true));
+ test_parser("eurt", backwards_bool(false));
+ //]
+ }
+
+ // sequence
+ {
+ //[reference_using_declarations_sequence
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::_2;
+ namespace bf = boost::fusion;
+ //]
+
+ //[reference_sequence
+ //`Simple usage:
+ test_parser("xy", char_ >> char_);
+
+ //`Extracting the attribute tuple (using __fusion__):
+ bf::vector<char, char> attr;
+ test_parser_attr("xy", char_ >> char_, attr);
+ std::cout << bf::at_c<0>(attr) << ',' << bf::at_c<1>(attr) << std::endl;
+
+ //`Extracting the attribute vector (using __stl__):
+ std::vector<char> vec;
+ test_parser_attr("xy", char_ >> char_, vec);
+ std::cout << vec[0] << ',' << vec[1] << std::endl;
+
+ //`Extracting the attributes using __qi_semantic_actions__ (using __phoenix__):
+ test_parser("xy", (char_ >> char_)[std::cout << _1 << ',' << _2 << std::endl]);
+ //]
+ }
+
+ // sequential_or
+ {
+ //[reference_using_declarations_sequential_or
+ using boost::spirit::qi::int_;
+ //]
+
+ //[reference_sequential_or
+ //`Correctly parsing a number with optional fractional digits:
+ test_parser("123.456", int_ || ('.' >> int_)); // full
+ test_parser("123", int_ || ('.' >> int_)); // just the whole number
+ test_parser(".456", int_ || ('.' >> int_)); // just the fraction
+
+ /*`A naive but incorrect solution would try to do this using optionals (e.g.):
+
+ int_ >> -('.' >> int_) // will not match ".456"
+ -int_ >> ('.' >> int_) // will not match "123"
+ -int_ >> -('.' >> int_) // will match empty strings! Ooops.
+ */
+ //]
+ }
+
+ // alternative
+ {
+ //[reference_using_declarations_alternative
+ using boost::spirit::ascii::string;
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::_1;
+ using boost::variant;
+ //]
+
+ //[reference_alternative
+ //`Simple usage:
+ test_parser("Hello", string("Hello") | int_);
+ test_parser("123", string("Hello") | int_);
+
+ //`Extracting the attribute variant (using __boost_variant__):
+ variant<std::string, int> attr;
+ test_parser_attr("Hello", string("Hello") | int_, attr);
+
+ /*`This should print `"Hello"`. Note: There are better ways to extract the value
+ from the variant. See __boost_variant__ visitation. This code is solely
+ for demonstration.
+ */
+ if (boost::get<int>(&attr))
+ std::cout << boost::get<int>(attr) << std::endl;
+ else
+ std::cout << boost::get<std::string>(attr) << std::endl;
+
+ /*`Extracting the attributes using __qi_semantic_actions__ with __phoenix__
+ (this should print `123`):
+ */
+ test_parser("123", (string("Hello") | int_)[std::cout << _1 << std::endl]);
+ //]
+
+ }
+
+ // permutation
+ {
+ //[reference_using_declarations_permutation
+ using boost::spirit::ascii::char_;
+ //]
+
+ //[reference_permutation
+ //`Parse a string containing DNA codes (ACTG)
+ test_parser("ACTGGCTAGACT", *(char_('A') ^ 'C' ^ 'T' ^ 'G'));
+ //]
+ }
+
+ // expect
+ {
+ //[reference_using_declarations_expect
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::expectation_failure;
+ //]
+
+ //[reference_expect
+ /*`The code below uses an expectation operator to throw an __qi_expectation_failure__
+ with a deliberate parsing error when `"o"` is expected and `"i"` is what is
+ found in the input. The `catch` block prints the information related to the
+ error. Note: This is low level code that demonstrates the /bare-metal/. Typically,
+ you use an __qi_error_handler__ to deal with the error.
+ */
+ try
+ {
+ test_parser("xi", char_('x') > char_('o')); // should throw an exception
+ }
+ catch (expectation_failure<char const*> const& x)
+ {
+ std::cout << "expected: "; print_info(x.what_);
+ std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
+ }
+ /*`The code above will print:[teletype]
+
+ expected: tag: literal-char, value: o
+ got: "i"``[c++]``
+ */
+ //]
+ }
+
+ // expectd
+ {
+ //[reference_using_declarations_expectd
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::expect;
+ using boost::spirit::qi::expectation_failure;
+ //]
+
+ //[reference_expectd
+ /*`The code below uses an expectation operator to throw an __qi_expectation_failure__
+ with a deliberate parsing error when `"o"` is expected and `"x"` is what is
+ found in the input. The `catch` block prints the information related to the
+ error. Note: This is low level code that demonstrates the /bare-metal/. Typically,
+ you use an __qi_error_handler__ to deal with the error.
+ */
+ try
+ {
+ test_parser("xi", expect[char_('o')]); // should throw an exception
+ }
+ catch (expectation_failure<char const*> const& x)
+ {
+ std::cout << "expected: "; print_info(x.what_);
+ std::cout << "got: \"" << std::string(x.first, x.last) << '"' << std::endl;
+ }
+ /*`The code above will print:[teletype]
+
+ expected: tag: literal-char, value: o
+ got: "x"``[c++]``
+ */
+ //]
+ }
+
+ // and-predicate
+ {
+ //[reference_and_predicate
+ //`Some using declarations:
+ using boost::spirit::lit;
+
+ /*`Basic look-ahead example: make sure that the last character is a
+ semicolon, but don't consume it, just peek at the next character:
+ */
+ test_phrase_parser("Hello ;", lit("Hello") >> &lit(';'), false);
+ //]
+ }
+
+ // not-predicate
+ {
+ //[reference_not_predicate
+ //`Some using declarations:
+ using boost::spirit::ascii::char_;
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::qi::lit;
+ using boost::spirit::qi::symbols;
+
+ /*`Here's an alternative to the `*(r - x) >> x` idiom using the
+ not-predicate instead. This parses a list of characters terminated
+ by a ';':
+ */
+ test_parser("abcdef;", *(!lit(';') >> char_) >> ';');
+
+ /*`The following parser ensures that we match distinct keywords
+ (stored in a symbol table). To do this, we make sure that the
+ keyword does not follow an alpha or an underscore:
+ */
+ symbols<char, int> keywords;
+ keywords = "begin", "end", "for";
+
+ // This should fail:
+ test_parser("beginner", keywords >> !(alpha | '_'));
+
+ // This is ok:
+ test_parser("end ", keywords >> !(alpha | '_'), false);
+
+ // This is ok:
+ test_parser("for()", keywords >> !(alpha | '_'), false);
+ //]
+ }
+
+ // difference
+ {
+ //[reference_difference
+ //`Some using declarations:
+ using boost::spirit::ascii::char_;
+
+ /*`Parse a C/C++ style comment:
+ */
+ test_parser("/*A Comment*/", "/*" >> *(char_ - "*/") >> "*/");
+ //]
+ }
+
+ // kleene
+ {
+ //[reference_kleene
+ //`Some using declarations:
+ using boost::spirit::qi::int_;
+
+ /*`Parse a comma separated list of numbers and put them in a vector:
+ */
+ std::vector<int> attr;
+ test_phrase_parser_attr(
+ "111, 222, 333, 444, 555", int_ >> *(',' >> int_), attr);
+ std::cout
+ << attr[0] << ',' << attr[1] << ',' << attr[2] << ','
+ << attr[3] << ',' << attr[4]
+ << std::endl;
+ //]
+ }
+
+ // plus
+ {
+ //[reference_plus
+ //`Some using declarations:
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::qi::lexeme;
+
+ /*`Parse one or more strings containing one or more alphabetic
+ characters and put them in a vector:
+ */
+ std::vector<std::string> attr;
+ test_phrase_parser_attr("yaba daba doo", +lexeme[+alpha], attr);
+ std::cout << attr[0] << ',' << attr[1] << ',' << attr[2] << std::endl;
+ //]
+ }
+
+ // optional
+ {
+ //[reference_optional
+ //`Some using declarations:
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::lexeme;
+ using boost::spirit::qi::int_;
+ using boost::fusion::vector;
+ using boost::fusion::at_c;
+ using boost::optional;
+
+ /*`Parse a person info with name (in quotes) optional age [footnote
+ James Bond is shy about his age :-)] and optional sex, all
+ separated by comma.
+ */
+ vector<std::string, optional<int>, optional<char> > attr;
+
+ test_phrase_parser_attr(
+ "\"James Bond\", M"
+ , lexeme['"' >> +(char_ - '"') >> '"'] // name
+ >> -(',' >> int_) // optional age
+ >> -(',' >> char_) // optional sex
+ , attr);
+
+ // Should print: James Bond,M
+ std::cout << at_c<0>(attr); // print name
+ if (at_c<1>(attr)) // print optional age
+ std::cout << ',' << *at_c<1>(attr);
+ if (at_c<2>(attr)) // print optional sex
+ std::cout << ',' << *at_c<2>(attr);
+ std::cout << std::endl;
+ //]
+ }
+
+ // list
+ {
+ //[reference_list
+ //`Some using declarations:
+ using boost::spirit::qi::int_;
+
+ /*`Parse a comma separated list of numbers and put them in a vector:
+ */
+ std::vector<int> attr;
+ test_phrase_parser_attr(
+ "111, 222, 333, 444, 555", int_ % ',', attr);
+ std::cout
+ << attr[0] << ',' << attr[1] << ',' << attr[2] << ','
+ << attr[3] << ',' << attr[4]
+ << std::endl;
+ //]
+ }
+
+ // stream
+ {
+ //[reference_qi_stream
+ //`Using declarations and variables:
+ using boost::spirit::qi::stream;
+ using boost::spirit::qi::stream_parser;
+
+ /*`Parse a simple string using the operator>>(istream&, std::string&);
+ */
+ std::string str;
+ test_parser_attr("abc", stream, str);
+ std::cout << str << std::endl; // prints: abc
+
+ /*`Parse our complex type using the operator>>(istream&, complex&);
+ */
+ complex c;
+ test_parser_attr("{1.0,2.5}", stream_parser<char, complex>(), c);
+ std::cout << c.a << "," << c.b << std::endl; // prints: 1.0,2.5
+ //]
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // auto module
+ {
+ //[reference_qi_using_declarations_auto
+ using boost::spirit::qi::auto_;
+ //]
+
+ //[reference_qi_auto
+ /*`Parse a simple integer using the generated parser component `int_`:
+ */
+ int i = 0;
+ test_parser_attr("123", auto_, i);
+ std::cout << i << std::endl; // prints: 123
+
+ /*`Parse an instance of the `complex` data type as defined above using
+ the parser as generated by the defined customization point:
+ */
+ complex c;
+ test_parser_attr("{1.2,2.4}", auto_, c);
+ std::cout << c.a << "," << c.b << std::endl; // prints: 1.2,2.4
+ //]
+ }
+
+ // native binary
+ {
+ //[reference_qi_native_binary
+ //`Using declarations and variables:
+ using boost::spirit::qi::byte_;
+ using boost::spirit::qi::word;
+ using boost::spirit::qi::dword;
+ using boost::spirit::qi::qword;
+
+ boost::uint8_t uc;
+ boost::uint16_t us;
+ boost::uint32_t ui;
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ boost::uint64_t ul;
+//<-
+#endif
+
+#if BOOST_ENDIAN_LITTLE_BYTE
+//->
+ //`Basic usage of the native binary parsers for little endian platforms:
+ test_parser_attr("\x01", byte_, uc); assert(uc == 0x01);
+ test_parser_attr("\x01\x02", word, us); assert(us == 0x0201);
+ test_parser_attr("\x01\x02\x03\x04", dword, ui); assert(ui == 0x04030201);
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul);
+ assert(ul == 0x0807060504030201LL);
+
+//<-
+#endif
+//->
+ test_parser("\x01", byte_(0x01));
+ test_parser("\x01\x02", word(0x0201));
+ test_parser("\x01\x02\x03\x04", dword(0x04030201));
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
+ qword(0x0807060504030201LL));
+//<-
+#endif
+#else
+//->
+ //`Basic usage of the native binary parsers for big endian platforms:
+ test_parser_attr("\x01", byte_, uc); assert(uc == 0x01);
+ test_parser_attr("\x01\x02", word, us); assert(us == 0x0102);
+ test_parser_attr("\x01\x02\x03\x04", dword, ui); assert(ui == 0x01020304);
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", qword, ul);
+ assert(0x0102030405060708LL);
+
+//<-
+#endif
+//->
+ test_parser("\x01", byte_(0x01));
+ test_parser("\x01\x02", word(0x0102));
+ test_parser("\x01\x02\x03\x04", dword(0x01020304));
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
+ qword(0x0102030405060708LL));
+//<-
+#endif
+#endif
+//->
+ //]
+ }
+
+ // little binary
+ {
+ //[reference_qi_little_binary
+ //`Using declarations and variables:
+ using boost::spirit::qi::little_word;
+ using boost::spirit::qi::little_dword;
+ using boost::spirit::qi::little_qword;
+
+ boost::uint16_t us;
+ boost::uint32_t ui;
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ boost::uint64_t ul;
+//<-
+#endif
+
+//->
+ //`Basic usage of the little endian binary parsers:
+ test_parser_attr("\x01\x02", little_word, us); assert(us == 0x0201);
+ test_parser_attr("\x01\x02\x03\x04", little_dword, ui); assert(ui == 0x04030201);
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", little_qword, ul);
+ assert(ul == 0x0807060504030201LL);
+
+//<-
+#endif
+//->
+ test_parser("\x01\x02", little_word(0x0201));
+ test_parser("\x01\x02\x03\x04", little_dword(0x04030201));
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
+ little_qword(0x0807060504030201LL));
+//<-
+#endif
+//->
+ //]
+ }
+
+ // big binary
+ {
+ //[reference_qi_big_binary
+ //`Using declarations and variables:
+ using boost::spirit::qi::big_word;
+ using boost::spirit::qi::big_dword;
+ using boost::spirit::qi::big_qword;
+
+ boost::uint16_t us;
+ boost::uint32_t ui;
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ boost::uint64_t ul;
+//<-
+#endif
+
+//->
+ //`Basic usage of the big endian binary parsers:
+ test_parser_attr("\x01\x02", big_word, us); assert(us == 0x0102);
+ test_parser_attr("\x01\x02\x03\x04", big_dword, ui); assert(ui == 0x01020304);
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser_attr("\x01\x02\x03\x04\x05\x06\x07\x08", big_qword, ul);
+ assert(0x0102030405060708LL);
+
+//<-
+#endif
+//->
+ test_parser("\x01\x02", big_word(0x0102));
+ test_parser("\x01\x02\x03\x04", big_dword(0x01020304));
+//<-
+#ifdef BOOST_HAS_LONG_LONG
+//->
+ test_parser("\x01\x02\x03\x04\x05\x06\x07\x08",
+ big_qword(0x0102030405060708LL));
+//<-
+#endif
+//->
+ //]
+ }
+
+ // rule
+ {
+ //[reference_rule
+ //`Some using declarations:
+ using boost::spirit::qi::rule;
+ using boost::spirit::qi::int_;
+ using boost::spirit::qi::locals;
+ using boost::spirit::qi::_1;
+ using boost::spirit::qi::_a;
+ using boost::spirit::ascii::alpha;
+ using boost::spirit::ascii::char_;
+ using boost::spirit::ascii::space_type;
+
+ /*`Basic rule:
+ */
+ rule<char const*> r;
+ r = int_;
+ test_parser("123", r);
+
+ /*`Rule with synthesized attribute:
+ */
+ rule<char const*, int()> ra;
+ ra = int_;
+ int i;
+ test_parser_attr("123", ra, i);
+ assert(i == 123);
+
+ /*`Rule with skipper and synthesized attribute:
+ */
+ rule<char const*, std::vector<int>(), space_type> rs;
+ rs = *int_;
+ std::vector<int> v;
+ test_phrase_parser_attr("123 456 789", rs, v);
+ assert(v[0] == 123);
+ assert(v[1] == 456);
+ assert(v[2] == 789);
+
+ /*`Rule with one local variable:
+ */
+ rule<char const*, locals<char> > rl;
+ rl = alpha[_a = _1] >> char_(_a); // get two identical characters
+ test_parser("aa", rl); // pass
+ test_parser("ax", rl); // fail
+ //]
+ }
+
+ // grammar
+ {
+ using client::num_list;
+
+ //[reference_grammar_using
+ //`Some using declarations:
+ using boost::spirit::ascii::space_type;
+ using boost::spirit::int_;
+ using boost::spirit::qi::grammar;
+ using boost::spirit::qi::rule;
+ //]
+
+ //[reference_grammar
+ //`How to use the example grammar:
+ num_list nlist;
+ test_phrase_parser("123, 456, 789", nlist);
+ //]
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/qi/reorder_struct.cpp b/src/boost/libs/spirit/example/qi/reorder_struct.cpp
new file mode 100644
index 00000000..5f5a50b1
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/reorder_struct.cpp
@@ -0,0 +1,130 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// The main purpose of this example is to show how a single fusion sequence
+// can be filled from a parsed input of the elements in different sequences
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/mpl/print.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/fusion/include/struct.hpp>
+#include <boost/fusion/include/nview.hpp>
+#include <boost/foreach.hpp>
+
+namespace fusion = boost::fusion;
+namespace qi = boost::spirit::qi;
+
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ // Our employee struct
+ struct employee
+ {
+ std::string surname;
+ std::string forename;
+ int age;
+ double salary;
+ std::string department;
+ };
+
+ // define iterator type
+ typedef std::string::const_iterator iterator_type;
+
+ // This is the output routine taking a format description and the data to
+ // print
+ template <typename Parser, typename Sequence>
+ bool parse(std::string const& input, Parser const& p, Sequence& s)
+ {
+ iterator_type begin = input.begin();
+ return qi::parse(begin, input.end(), p, s);
+ }
+}
+
+// We need to tell fusion about our employee struct to make it a first-class
+// fusion citizen. This has to be in global scope. Note that we don't need to
+// list the members of our struct in the same sequence a they are defined
+BOOST_FUSION_ADAPT_STRUCT(
+ client::employee,
+ (int, age)
+ (std::string, surname)
+ (std::string, forename)
+ (std::string, department)
+ (double, salary)
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// that's the different types we need to reorder the attributes
+typedef fusion::result_of::as_nview<client::employee, 2, 0>::type name_and_age;
+typedef fusion::result_of::as_nview<client::employee, 1, 2, 4>::type names_and_salary;
+typedef fusion::result_of::as_nview<client::employee, 2, 0, 3>::type name_age_and_department;
+
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ std::string str;
+
+ // some employees
+ client::employee john;
+ client::employee mary;
+ client::employee tom;
+
+ // print data about employees in different formats
+ {
+ // parse forename and age only
+ name_and_age johnview(fusion::as_nview<2, 0>(john));
+ bool r = client::parse(
+ "John, 25",
+ *(qi::char_ - ',') >> ", " >> qi::int_,
+ johnview);
+ if (r) {
+ std::cout << "Parsed: " << john.forename << ", " << john.age
+ << std::endl;
+ }
+
+ // parse surname, forename, and salary
+ names_and_salary maryview(fusion::as_nview<1, 2, 4>(mary));
+ r = client::parse(
+ "Higgins, Mary: 2200.36",
+ *(qi::char_ - ',') >> ", " >> *(qi::char_ - ':') >> ": " >> qi::double_,
+ maryview);
+ if (r) {
+ std::cout << "Parsed: " << mary.forename << ", " << mary.surname
+ << ", " << mary.salary << std::endl;
+ }
+
+ // parse forename, age, and department
+ name_age_and_department tomview(fusion::as_nview<2, 0, 3>(tom));
+ client::parse(
+ "Tom: 48 (Boss)",
+ *(qi::char_ - ':') >> ": " >> qi::int_ >> " (" >> *(qi::char_ - ')') >> ')',
+ tomview);
+ if (r) {
+ std::cout << "Parsed: " << tom.forename << ", " << tom.age
+ << ", " << tom.department << std::endl;
+ }
+ }
+
+ // now parse a list of several employees and print them all
+ std::vector<client::employee> employees;
+
+ // parse surname, forename, and salary for all employees
+ {
+ qi::rule<client::iterator_type, names_and_salary()> r =
+ *(qi::char_ - ',') >> ", " >> *(qi::char_ - ',') >> ", " >> qi::double_;
+
+ bool result = client::parse(
+ "John, Smith, 2000.50\n" "Mary, Higgins, 2200.36\n" "Tom, Taylor, 3200.00\n",
+ r % qi::eol, employees);
+
+ std::cout << "Parsed: " << std::endl;
+ BOOST_FOREACH(client::employee const& e, employees)
+ {
+ std::cout << e.forename << ", " << e.surname << ", " << e.salary
+ << std::endl;
+ }
+ }
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/qi/roman.cpp b/src/boost/libs/spirit/example/qi/roman.cpp
new file mode 100644
index 00000000..e98c2a8a
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/roman.cpp
@@ -0,0 +1,188 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Roman Numerals Parser (demonstrating the symbol table). This is
+// discussed in the "Symbols" chapter in the Spirit User's Guide.
+//
+// [ JDG August 22, 2002 ] spirit1
+// [ JDG March 13, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Parse roman hundreds (100..900) numerals using the symbol table.
+ // Notice that the data associated with each slot is the parser's attribute
+ // (which is passed to attached semantic actions).
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_roman_hundreds
+ struct hundreds_ : qi::symbols<char, unsigned>
+ {
+ hundreds_()
+ {
+ add
+ ("C" , 100)
+ ("CC" , 200)
+ ("CCC" , 300)
+ ("CD" , 400)
+ ("D" , 500)
+ ("DC" , 600)
+ ("DCC" , 700)
+ ("DCCC" , 800)
+ ("CM" , 900)
+ ;
+ }
+
+ } hundreds;
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Parse roman tens (10..90) numerals using the symbol table.
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_roman_tens
+ struct tens_ : qi::symbols<char, unsigned>
+ {
+ tens_()
+ {
+ add
+ ("X" , 10)
+ ("XX" , 20)
+ ("XXX" , 30)
+ ("XL" , 40)
+ ("L" , 50)
+ ("LX" , 60)
+ ("LXX" , 70)
+ ("LXXX" , 80)
+ ("XC" , 90)
+ ;
+ }
+
+ } tens;
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Parse roman ones (1..9) numerals using the symbol table.
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_roman_ones
+ struct ones_ : qi::symbols<char, unsigned>
+ {
+ ones_()
+ {
+ add
+ ("I" , 1)
+ ("II" , 2)
+ ("III" , 3)
+ ("IV" , 4)
+ ("V" , 5)
+ ("VI" , 6)
+ ("VII" , 7)
+ ("VIII" , 8)
+ ("IX" , 9)
+ ;
+ }
+
+ } ones;
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // roman (numerals) grammar
+ //
+ // Note the use of the || operator. The expression
+ // a || b reads match a or b and in sequence. Try
+ // defining the roman numerals grammar in YACC or
+ // PCCTS. Spirit rules! :-)
+ ///////////////////////////////////////////////////////////////////////////////
+ //[tutorial_roman_grammar
+ template <typename Iterator>
+ struct roman : qi::grammar<Iterator, unsigned()>
+ {
+ roman() : roman::base_type(start)
+ {
+ using qi::eps;
+ using qi::lit;
+ using qi::_val;
+ using qi::_1;
+ using ascii::char_;
+
+ start = eps [_val = 0] >>
+ (
+ +lit('M') [_val += 1000]
+ || hundreds [_val += _1]
+ || tens [_val += _1]
+ || ones [_val += _1]
+ )
+ ;
+ }
+
+ qi::rule<Iterator, unsigned()> start;
+ };
+ //]
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tRoman Numerals Parser\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type a Roman Numeral ...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::roman<iterator_type> roman;
+
+ roman roman_parser; // Our grammar
+
+ std::string str;
+ unsigned result;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ //[tutorial_roman_grammar_parse
+ bool r = parse(iter, end, roman_parser, result);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "result = " << result << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ //]
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/sum.cpp b/src/boost/libs/spirit/example/qi/sum.cpp
new file mode 100644
index 00000000..33310aa5
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/sum.cpp
@@ -0,0 +1,106 @@
+/*=============================================================================
+ Copyright (c) 2002-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A parser for summing a comma-separated list of numbers using phoenix.
+//
+// [ JDG June 28, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+//[tutorial_adder_includes
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+#include <iostream>
+#include <string>
+//]
+
+namespace client
+{
+ //[tutorial_adder_using
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+ namespace phoenix = boost::phoenix;
+
+ using qi::double_;
+ using qi::_1;
+ using ascii::space;
+ using phoenix::ref;
+ //]
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our adder
+ ///////////////////////////////////////////////////////////////////////////
+
+ //[tutorial_adder
+ template <typename Iterator>
+ bool adder(Iterator first, Iterator last, double& n)
+ {
+ bool r = qi::phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[ref(n) = _1] >> *(',' >> double_[ref(n) += _1])
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA parser for summing a list of numbers...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers are added using Phoenix.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ double n;
+ if (client::adder(str.begin(), str.end(), n))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ std::cout << "sum = " << n;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/typeof.cpp b/src/boost/libs/spirit/example/qi/typeof.cpp
new file mode 100644
index 00000000..90e8fb0e
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/typeof.cpp
@@ -0,0 +1,65 @@
+/*=============================================================================
+ Copyright (c) 2001-2010 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/qi_copy.hpp>
+#include <boost/spirit/include/support_auto.hpp>
+#include <iostream>
+#include <string>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+
+int
+main()
+{
+ using boost::spirit::ascii::space;
+ using boost::spirit::ascii::char_;
+ using boost::spirit::qi::parse;
+ typedef std::string::const_iterator iterator_type;
+
+///////////////////////////////////////////////////////////////////////////////
+// this works for non-c++11 compilers
+#ifdef BOOST_NO_CXX11_AUTO_DECLARATIONS
+
+ BOOST_SPIRIT_AUTO(qi, comment, "/*" >> *(char_ - "*/") >> "*/");
+
+///////////////////////////////////////////////////////////////////////////////
+// but this is better for c++11 compilers with auto
+#else
+
+ using boost::spirit::qi::copy;
+
+ auto comment = copy("/*" >> *(char_ - "*/") >> "*/");
+
+#endif
+
+ std::string str = "/*This is a comment*/";
+ std::string::const_iterator iter = str.begin();
+ std::string::const_iterator end = str.end();
+ bool r = parse(iter, end, comment);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+
+ return 0;
+}
+
+
diff --git a/src/boost/libs/spirit/example/qi/unescaped_string.cpp b/src/boost/libs/spirit/example/qi/unescaped_string.cpp
new file mode 100644
index 00000000..4a0d6002
--- /dev/null
+++ b/src/boost/libs/spirit/example/qi/unescaped_string.cpp
@@ -0,0 +1,72 @@
+// Copyright (c) 2010 Jeroen Habraken
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/spirit/include/qi.hpp>
+
+#include <iostream>
+#include <ostream>
+#include <string>
+
+namespace client
+{
+ namespace qi = boost::spirit::qi;
+
+ template <typename InputIterator>
+ struct unescaped_string
+ : qi::grammar<InputIterator, std::string(char const*)>
+ {
+ unescaped_string()
+ : unescaped_string::base_type(unesc_str)
+ {
+ unesc_char.add("\\a", '\a')("\\b", '\b')("\\f", '\f')("\\n", '\n')
+ ("\\r", '\r')("\\t", '\t')("\\v", '\v')("\\\\", '\\')
+ ("\\\'", '\'')("\\\"", '\"')
+ ;
+
+ unesc_str = qi::lit(qi::_r1)
+ >> *(unesc_char | qi::alnum | "\\x" >> qi::hex)
+ >> qi::lit(qi::_r1)
+ ;
+ }
+
+ qi::rule<InputIterator, std::string(char const*)> unesc_str;
+ qi::symbols<char const, char const> unesc_char;
+ };
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main()
+{
+ namespace qi = boost::spirit::qi;
+
+ typedef std::string::const_iterator iterator_type;
+
+ std::string parsed;
+
+ std::string str("'''string\\x20to\\x20unescape\\x3a\\x20\\n\\r\\t\\\"\\'\\x41'''");
+ char const* quote = "'''";
+
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+
+ client::unescaped_string<iterator_type> p;
+ if (!qi::parse(iter, end, p(quote), parsed))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsed: " << parsed << "\n";
+ std::cout << "-------------------------\n";
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/support/Jamfile b/src/boost/libs/spirit/example/support/Jamfile
new file mode 100644
index 00000000..273e341b
--- /dev/null
+++ b/src/boost/libs/spirit/example/support/Jamfile
@@ -0,0 +1,16 @@
+#==============================================================================
+# Copyright (c) 2001-2011 Joel de Guzman
+# Copyright (c) 2001-2011 Hartmut Kaiser
+# Copyright (C) 2011 Bryce Lelbach
+#
+# Distributed under the 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-support-example
+ : requirements <toolset>gcc:<c++-template-depth>300
+ :
+ :
+ ;
+
+exe multi_pass : multi_pass.cpp ;
+exe parse_sexpr : utree/parse_sexpr.cpp ;
diff --git a/src/boost/libs/spirit/example/support/multi_pass.cpp b/src/boost/libs/spirit/example/support/multi_pass.cpp
new file mode 100644
index 00000000..27e529c7
--- /dev/null
+++ b/src/boost/libs/spirit/example/support/multi_pass.cpp
@@ -0,0 +1,50 @@
+// Copyright (c) 2001-2010 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+#include <boost/spirit/include/qi.hpp>
+#include <boost/spirit/include/support_multi_pass.hpp>
+
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+//[tutorial_multi_pass
+int main()
+{
+ namespace spirit = boost::spirit;
+ using spirit::ascii::space;
+ using spirit::ascii::char_;
+ using spirit::qi::double_;
+ using spirit::qi::eol;
+
+ std::ifstream in("multi_pass.txt"); // we get our input from this file
+ if (!in.is_open()) {
+ std::cout << "Could not open input file: 'multi_pass.txt'" << std::endl;
+ return -1;
+ }
+
+ typedef std::istreambuf_iterator<char> base_iterator_type;
+ spirit::multi_pass<base_iterator_type> first =
+ spirit::make_default_multi_pass(base_iterator_type(in));
+
+ std::vector<double> v;
+ bool result = spirit::qi::phrase_parse(first
+ , spirit::make_default_multi_pass(base_iterator_type())
+ , double_ >> *(',' >> double_) // recognize list of doubles
+ , space | '#' >> *(char_ - eol) >> eol // comment skipper
+ , v); // data read from file
+
+ if (!result) {
+ std::cout << "Failed parsing input file!" << std::endl;
+ return -2;
+ }
+
+ std::cout << "Successfully parsed input file!" << std::endl;
+ return 0;
+}
+//]
diff --git a/src/boost/libs/spirit/example/support/multi_pass.txt b/src/boost/libs/spirit/example/support/multi_pass.txt
new file mode 100644
index 00000000..54368f38
--- /dev/null
+++ b/src/boost/libs/spirit/example/support/multi_pass.txt
@@ -0,0 +1,6 @@
+# Copyright (c) 2001-2009 Hartmut Kaiser
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+1.0,2.0,3.0
diff --git a/src/boost/libs/spirit/example/support/utree/error_handler.hpp b/src/boost/libs/spirit/example/support/utree/error_handler.hpp
new file mode 100644
index 00000000..6f5ba1bc
--- /dev/null
+++ b/src/boost/libs/spirit/example/support/utree/error_handler.hpp
@@ -0,0 +1,112 @@
+/*==============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2010-2011 Bryce Lelbach
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_UTREE_EXAMPLE_ERROR_HANDLER_HPP
+
+#include <string>
+#include <sstream>
+
+#include <boost/config.hpp>
+#include <boost/spirit/home/support/info.hpp>
+#include <boost/spirit/include/support_line_pos_iterator.hpp>
+
+namespace sexpr
+{
+
+using boost::spirit::info;
+
+template <typename Out>
+struct print_info
+{
+ typedef boost::spirit::utf8_string string;
+
+ print_info(Out& out) : out(out), first(true) {}
+
+ void element(string const& tag, string const& value, int) const
+ {
+ if (!first) {
+ out << ' ';
+ first = false;
+ }
+
+ if (value == "")
+ out << tag;
+ else
+ out << "\"" << value << '"';
+ }
+
+ Out& out;
+ mutable bool first;
+};
+
+struct expected_component : std::exception
+{
+ std::string msg;
+
+ expected_component(std::string const& source, std::size_t line
+ , info const& w)
+ {
+ using boost::spirit::basic_info_walker;
+
+ std::ostringstream oss;
+ oss << "(exception \"" << source << "\" ";
+
+ if (line == -1)
+ oss << -1;
+ else
+ oss << line;
+
+ oss << " '(expected_component (";
+
+ print_info<std::ostringstream> pr(oss);
+ basic_info_walker<print_info<std::ostringstream> >
+ walker(pr, w.tag, 0);
+
+ boost::apply_visitor(walker, w.value);
+
+ oss << ")))";
+
+ msg = oss.str();
+ }
+
+ virtual ~expected_component() BOOST_NOEXCEPT_OR_NOTHROW {}
+
+ virtual char const* what() const BOOST_NOEXCEPT_OR_NOTHROW
+ {
+ return msg.c_str();
+ }
+};
+
+template <typename Iterator>
+struct error_handler
+{
+ template <typename, typename, typename, typename>
+ struct result
+ {
+ typedef void type;
+ };
+
+ std::string source;
+
+ error_handler(std::string const& source_ = "<string>") : source(source_) {}
+
+ void operator()(Iterator first, Iterator last, Iterator err_pos
+ , info const& what) const
+ {
+ using boost::spirit::get_line;
+ Iterator eol = err_pos;
+ std::size_t line = get_line(err_pos);
+ throw expected_component(source, line, what);
+ }
+};
+
+} // sexpr
+
+#endif // BOOST_SPIRIT_UTREE_EXAMPLE_ERROR_HANDLER_HPP
+
diff --git a/src/boost/libs/spirit/example/support/utree/parse_sexpr.cpp b/src/boost/libs/spirit/example/support/utree/parse_sexpr.cpp
new file mode 100644
index 00000000..72d49ea5
--- /dev/null
+++ b/src/boost/libs/spirit/example/support/utree/parse_sexpr.cpp
@@ -0,0 +1,62 @@
+/*==============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2010-2011 Bryce Lelbach
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#include <boost/spirit/include/support_istream_iterator.hpp>
+#include <boost/spirit/include/support_line_pos_iterator.hpp>
+#include <boost/spirit/include/qi_parse.hpp>
+
+#include "sexpr_parser.hpp"
+
+int
+main()
+{
+ using boost::spirit::qi::phrase_parse;
+
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "sexpr 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 sexpr::parser<iterator_type> parser;
+ typedef sexpr::whitespace<iterator_type> space;
+
+ parser p;
+ space ws;
+
+ 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, p, ws);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
+
diff --git a/src/boost/libs/spirit/example/support/utree/sexpr_generator.hpp b/src/boost/libs/spirit/example/support/utree/sexpr_generator.hpp
new file mode 100644
index 00000000..5dc56223
--- /dev/null
+++ b/src/boost/libs/spirit/example/support/utree/sexpr_generator.hpp
@@ -0,0 +1,128 @@
+/*==============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+ Copyright (c) 2010-2011 Bryce Lelbach
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP)
+#define BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP
+
+#include <boost/spirit/include/support_utree.hpp>
+#include <boost/spirit/include/karma.hpp>
+
+namespace boost {
+namespace spirit {
+namespace traits {
+
+template<>
+struct transform_attribute<utree::nil_type, unused_type, karma::domain> {
+ typedef unused_type type;
+
+ static unused_type pre (utree::nil_type&) { return unused_type(); }
+};
+
+} // traits
+} // spirit
+} // boost
+
+namespace sexpr
+{
+
+namespace karma = boost::spirit::karma;
+namespace standard = boost::spirit::standard;
+
+using boost::spirit::utree;
+using boost::spirit::utf8_symbol_range_type;
+using boost::spirit::utf8_string_range_type;
+using boost::spirit::binary_range_type;
+
+struct bool_output_policies : karma::bool_policies<>
+{
+ template <typename CharEncoding, typename Tag, typename Iterator>
+ static bool generate_true(Iterator& sink, bool)
+ {
+ return string_inserter<CharEncoding, Tag>::call(sink, "#t");
+ }
+
+ template <typename CharEncoding, typename Tag, typename Iterator>
+ static bool generate_false(Iterator& sink, bool)
+ {
+ return string_inserter<CharEncoding, Tag>::call(sink, "#f");
+ }
+};
+
+template <typename Iterator>
+struct generator : karma::grammar<Iterator, utree()>
+{
+ typedef boost::iterator_range<utree::const_iterator> utree_list;
+
+ karma::rule<Iterator, utree()>
+ start, ref_;
+
+ karma::rule<Iterator, utree_list()>
+ list;
+
+ karma::rule<Iterator, utf8_symbol_range_type()>
+ symbol;
+
+ karma::rule<Iterator, utree::nil_type()>
+ nil_;
+
+ karma::rule<Iterator, utf8_string_range_type()>
+ utf8;
+
+ karma::rule<Iterator, binary_range_type()>
+ binary;
+
+ generator() : generator::base_type(start)
+ {
+ using standard::char_;
+ using standard::string;
+ using karma::bool_generator;
+ using karma::uint_generator;
+ using karma::double_;
+ using karma::int_;
+ using karma::lit;
+ using karma::right_align;
+
+ uint_generator<unsigned char, 16> hex2;
+ bool_generator<bool, bool_output_policies> boolean;
+
+ start = nil_
+ | double_
+ | int_
+ | boolean
+ | utf8
+ | symbol
+ | binary
+ | list
+ | ref_;
+
+ ref_ = start;
+
+ list = '(' << -(start % ' ') << ')';
+
+ utf8 = '"' << *(&char_('"') << "\\\"" | char_) << '"';
+
+ symbol = string;
+
+ binary = '#' << *right_align(2, '0')[hex2] << '#';
+
+ nil_ = karma::attr_cast(lit("nil"));
+
+ start.name("sexpr");
+ ref_.name("ref");
+ list.name("list");
+ utf8.name("string");
+ symbol.name("symbol");
+ binary.name("binary");
+ nil_.name("nil");
+ }
+};
+
+} // sexpr
+
+#endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_GENERATOR_HPP
+
diff --git a/src/boost/libs/spirit/example/support/utree/sexpr_parser.hpp b/src/boost/libs/spirit/example/support/utree/sexpr_parser.hpp
new file mode 100644
index 00000000..15dfdfbd
--- /dev/null
+++ b/src/boost/libs/spirit/example/support/utree/sexpr_parser.hpp
@@ -0,0 +1,250 @@
+/*==============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2010-2011 Bryce Lelbach
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP)
+#define BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP
+
+#include "utf8_parser.hpp"
+#include "error_handler.hpp"
+
+namespace boost {
+namespace spirit {
+namespace traits {
+
+template<>
+struct transform_attribute<utree::nil_type, unused_type, qi::domain> {
+ typedef unused_type type;
+
+ static unused_type pre (utree::nil_type&) { return unused_type(); }
+ static void post (utree::nil_type&, unused_type) { }
+ static void fail (utree::nil_type&) { }
+};
+
+} // traits
+} // spirit
+} // boost
+
+namespace sexpr
+{
+
+namespace qi = boost::spirit::qi;
+namespace px = boost::phoenix;
+namespace standard = boost::spirit::standard;
+
+using boost::spirit::utree;
+using boost::spirit::utf8_symbol_type;
+using boost::spirit::utf8_string_type;
+using boost::spirit::binary_string_type;
+
+struct bool_input_policies
+{
+ template <typename Iterator, typename Attribute>
+ static bool
+ parse_true(Iterator& first, Iterator const& last, Attribute& attr)
+ {
+ using boost::spirit::qi::detail::string_parse;
+ using boost::spirit::qi::bool_policies;
+ using boost::spirit::qi::unused;
+ using boost::spirit::traits::assign_to;
+ if (string_parse("#t", first, last, unused))
+ {
+ assign_to(true, attr); // result is true
+ return true;
+ }
+ return bool_policies<bool>::parse_true(first, last, attr);
+ }
+
+ template <typename Iterator, typename Attribute>
+ static bool
+ parse_false(Iterator& first, Iterator const& last, Attribute& attr)
+ {
+ using boost::spirit::qi::detail::string_parse;
+ using boost::spirit::qi::bool_policies;
+ using boost::spirit::qi::unused;
+ using boost::spirit::traits::assign_to;
+ if (string_parse("#f", first, last, unused))
+ {
+ assign_to(false, attr); // result is false
+ return true;
+ }
+ return bool_policies<bool>::parse_false(first, last, attr);
+ }
+};
+
+struct save_line_pos
+{
+ template <typename, typename>
+ struct result
+ {
+ typedef void type;
+ };
+
+ template <typename Range>
+ void operator()(utree& ast, Range const& rng) const
+ {
+ using boost::spirit::get_line;
+ std::size_t n = get_line(rng.begin());
+ if (n != -1)
+ {
+ BOOST_ASSERT(n <= (std::numeric_limits<short>::max)());
+ ast.tag(n);
+ }
+ else
+ ast.tag(-1);
+ }
+};
+
+template <typename Iterator, typename F>
+struct tagger : qi::grammar<Iterator, void(utree&, char)>
+{
+ qi::rule<Iterator, void(utree&, char)>
+ start;
+
+ qi::rule<Iterator, void(utree&)>
+ epsilon;
+
+ px::function<F>
+ f;
+
+ tagger(F f_ = F()) : tagger::base_type(start), f(f_)
+ {
+ using qi::omit;
+ using qi::raw;
+ using qi::eps;
+ using qi::lit;
+ using qi::_1;
+ using qi::_r1;
+ using qi::_r2;
+
+ start = omit[raw[lit(_r2)] [f(_r1, _1)]];
+
+ epsilon = omit[raw[eps] [f(_r1, _1)]];
+ }
+};
+
+template <typename Iterator>
+struct whitespace : qi::grammar<Iterator> {
+ qi::rule<Iterator>
+ start;
+
+ whitespace() : whitespace::base_type(start)
+ {
+ using standard::space;
+ using standard::char_;
+ using qi::eol;
+
+ start = space | (';' >> *(char_ - eol) >> eol);
+ }
+};
+
+} // sexpr
+
+//[utree_sexpr_parser
+namespace sexpr
+{
+
+template <typename Iterator, typename ErrorHandler = error_handler<Iterator> >
+struct parser : qi::grammar<Iterator, utree(), whitespace<Iterator> >
+{
+ qi::rule<Iterator, utree(), whitespace<Iterator> >
+ start, element, list;
+
+ qi::rule<Iterator, utree()>
+ atom;
+
+ qi::rule<Iterator, int()>
+ integer;
+
+ qi::rule<Iterator, utf8_symbol_type()>
+ symbol;
+
+ qi::rule<Iterator, utree::nil_type()>
+ nil_;
+
+ qi::rule<Iterator, binary_string_type()>
+ binary;
+
+ utf8::parser<Iterator>
+ string;
+
+ px::function<ErrorHandler> const
+ error;
+
+ tagger<Iterator, save_line_pos>
+ pos;
+
+ parser(std::string const& source_file = "<string>"):
+ parser::base_type(start), error(ErrorHandler(source_file))
+ {
+ using standard::char_;
+ using qi::unused_type;
+ using qi::lexeme;
+ using qi::hex;
+ using qi::oct;
+ using qi::no_case;
+ using qi::real_parser;
+ using qi::strict_real_policies;
+ using qi::uint_parser;
+ using qi::bool_parser;
+ using qi::on_error;
+ using qi::fail;
+ using qi::int_;
+ using qi::lit;
+ using qi::_val;
+ using qi::_1;
+ using qi::_2;
+ using qi::_3;
+ using qi::_4;
+
+ real_parser<double, strict_real_policies<double> > strict_double;
+ uint_parser<unsigned char, 16, 2, 2> hex2;
+ bool_parser<bool, sexpr::bool_input_policies> boolean;
+
+ start = element.alias();
+
+ element = atom | list;
+
+ list = pos(_val, '(') > *element > ')';
+
+ atom = nil_
+ | strict_double
+ | integer
+ | boolean
+ | string
+ | symbol
+ | binary;
+
+ nil_ = qi::attr_cast(lit("nil"));
+
+ integer = lexeme[ no_case["#x"] > hex]
+ | lexeme[ no_case["#o"] >> oct]
+ | lexeme[-no_case["#d"] >> int_];
+
+ std::string exclude = std::string(" ();\"\x01-\x1f\x7f") + '\0';
+ symbol = lexeme[+(~char_(exclude))];
+
+ binary = lexeme['#' > *hex2 > '#'];
+
+ start.name("sexpr");
+ element.name("element");
+ list.name("list");
+ atom.name("atom");
+ nil_.name("nil");
+ integer.name("integer");
+ symbol.name("symbol");
+ binary.name("binary");
+
+ on_error<fail>(start, error(_1, _2, _3, _4));
+ }
+};
+
+} // sexpr
+//]
+
+#endif // BOOST_SPIRIT_UTREE_EXAMPLE_SEXPR_PARSER_HPP
+
diff --git a/src/boost/libs/spirit/example/support/utree/utf8_parser.hpp b/src/boost/libs/spirit/example/support/utree/utf8_parser.hpp
new file mode 100644
index 00000000..b06046ae
--- /dev/null
+++ b/src/boost/libs/spirit/example/support/utree/utf8_parser.hpp
@@ -0,0 +1,138 @@
+/*==============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2010-2011 Bryce Lelbach
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file BOOST_LICENSE_1_0.rst or copy at http://www.boost.org/LICENSE_1_0.txt)
+==============================================================================*/
+
+#if !defined(BOOST_SPIRIT_UTREE_EXAMPLE_UTF8_PARSER_HPP)
+#define BOOST_SPIRIT_UTREE_EXAMPLE_UTF8_PARSER_HPP
+
+#include <string>
+
+#include <boost/cstdint.hpp>
+
+#include <boost/regex/pending/unicode_iterator.hpp>
+
+#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/spirit/include/support_utree.hpp>
+
+namespace utf8
+{
+
+namespace qi = boost::spirit::qi;
+namespace px = boost::phoenix;
+namespace standard = boost::spirit::standard;
+
+using boost::spirit::utree;
+using boost::spirit::utf8_symbol_type;
+using boost::spirit::utf8_string_type;
+using boost::spirit::binary_string_type;
+
+typedef boost::uint32_t uchar;
+
+struct push_string
+{
+ template <typename, typename>
+ struct result
+ {
+ typedef void type;
+ };
+
+ void operator()(std::string& s, uchar code_point) const
+ {
+ typedef std::back_insert_iterator<std::string> insert_iter;
+ insert_iter out_iter(s);
+ boost::utf8_output_iterator<insert_iter> s_iter(out_iter);
+ *s_iter++ = code_point;
+ }
+};
+
+struct push_escaped_string
+{
+ template <typename, typename>
+ struct result
+ {
+ typedef void type;
+ };
+
+ void operator()(std::string& s, uchar c) const
+ {
+ switch (c) {
+ case 'b':
+ s += '\b';
+ break;
+ case 't':
+ s += '\t';
+ break;
+ case 'n':
+ s += '\n';
+ break;
+ case 'f':
+ s += '\f';
+ break;
+ case 'r':
+ s += '\r';
+ break;
+ case '"':
+ s += '"';
+ break;
+ case '\\':
+ s += '\\';
+ break;
+ }
+ }
+};
+
+template <typename Iterator>
+struct parser : qi::grammar<Iterator, std::string()>
+{
+ qi::rule<Iterator, void(std::string&)>
+ escaped;
+
+ qi::rule<Iterator, std::string()>
+ start;
+
+ px::function<push_string>
+ push_str;
+
+ px::function<push_escaped_string>
+ push_esc;
+
+ parser() : parser::base_type (start)
+ {
+ using standard::char_;
+ using qi::uint_parser;
+ using qi::_val;
+ using qi::_r1;
+ using qi::_1;
+
+ uint_parser<uchar, 16, 4, 4> hex4;
+ uint_parser<uchar, 16, 8, 8> hex8;
+
+ escaped
+ = '\\'
+ > ( ('u' > hex4) [push_str(_r1, _1)]
+ | ('U' > hex8) [push_str(_r1, _1)]
+ | char_("btnfr\\\"'") [push_esc(_r1, _1)]
+ );
+
+ start
+ = '"'
+ > *(escaped(_val) | (~char_('"')) [_val += _1])
+ > '"';
+
+ escaped.name("escaped_string");
+ start.name("string");
+ }
+};
+
+} // utf8
+
+#endif // BOOST_SPIRIT_UTREE_EXAMPLE_UTF8_PARSER_HPP
+
diff --git a/src/boost/libs/spirit/example/x3/Jamfile b/src/boost/libs/spirit/example/x3/Jamfile
new file mode 100644
index 00000000..1e8bb8f3
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/Jamfile
@@ -0,0 +1,65 @@
+#==============================================================================
+# Copyright (c) 2001-2014 Joel de Guzman
+#
+# Distributed under the 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-x3-example
+ : requirements
+ <include>.
+ <c++-template-depth>512
+ <toolset>gcc:<cxxflags>-std=c++1y
+ <toolset>clang:<cxxflags>-std=c++1y
+ <toolset>darwin:<cxxflags>-std=c++1y
+ :
+ :
+ ;
+
+exe x3_num_list1 : num_list/num_list1.cpp ;
+exe x3_num_list2 : num_list/num_list2.cpp ;
+exe x3_num_list3 : num_list/num_list3.cpp ;
+exe x3_num_list4 : num_list/num_list4.cpp ;
+
+exe x3_actions : actions.cpp ;
+exe x3_complex_number : complex_number.cpp ;
+exe x3_sum : sum.cpp ;
+exe x3_roman : roman.cpp ;
+exe x3_employee : employee.cpp ;
+
+exe x3_rexpr : rexpr/rexpr_min/rexpr.cpp ;
+
+build-project rexpr/rexpr_full ;
+
+exe x3_calc1 : calc/calc1.cpp ;
+exe x3_calc2 : calc/calc2.cpp ;
+exe x3_calc4 : calc/calc4.cpp ;
+exe x3_calc4b : calc/calc4b.cpp ;
+exe x3_calc5 : calc/calc5.cpp ;
+exe x3_calc6 : calc/calc6.cpp ;
+
+exe x3_calc7 :
+ calc/calc7/vm.cpp
+ calc/calc7/compiler.cpp
+ calc/calc7/expression.cpp
+ calc/calc7/main.cpp
+;
+
+exe x3_calc8 :
+ /boost//filesystem
+ calc/calc8/vm.cpp
+ calc/calc8/compiler.cpp
+ calc/calc8/expression.cpp
+ calc/calc8/statement.cpp
+ calc/calc8/main.cpp
+;
+
+exe x3_calc9 :
+ /boost//filesystem
+ calc/calc9/vm.cpp
+ calc/calc9/compiler.cpp
+ calc/calc9/expression.cpp
+ calc/calc9/statement.cpp
+ calc/calc9/main.cpp
+;
+
+exe x3_tuple : attributes/tuple.cpp ; \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/actions.cpp b/src/boost/libs/spirit/example/x3/actions.cpp
new file mode 100644
index 00000000..7a80fe83
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/actions.cpp
@@ -0,0 +1,52 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include <iostream>
+
+// Presented are various ways to attach semantic actions
+// * Using plain function pointer
+// * Using simple function object
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ using x3::_attr;
+
+ struct print_action
+ {
+ template <typename Context>
+ void operator()(Context const& ctx) const
+ {
+ std::cout << _attr(ctx) << std::endl;
+ }
+ };
+}
+
+int main()
+{
+ using boost::spirit::x3::int_;
+ using boost::spirit::x3::parse;
+ using client::print_action;
+
+ { // example using function object
+
+ char const *first = "{43}", *last = first + std::strlen(first);
+ parse(first, last, '{' >> int_[print_action()] >> '}');
+ }
+
+ { // example using C++14 lambda
+
+ using boost::spirit::x3::_attr;
+ char const *first = "{44}", *last = first + std::strlen(first);
+ auto f = [](auto& ctx){ std::cout << _attr(ctx) << std::endl; };
+ parse(first, last, '{' >> int_[f] >> '}');
+ }
+
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/annotation.cpp b/src/boost/libs/spirit/example/x3/annotation.cpp
new file mode 100644
index 00000000..12dacfbb
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/annotation.cpp
@@ -0,0 +1,246 @@
+/*=============================================================================
+ Copyright (c) 2002-2018 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Based on the employee parser (see employee.cpp), this example shows how
+// to annotate the AST with the iterator positions for access to the source
+// code when post processing. This example also shows how to "inject" client
+// data, using the "with" directive, that the handlers can access.
+//
+// [ JDG May 9, 2007 ]
+// [ JDG May 13, 2015 ] spirit X3
+// [ JDG Feb 22, 2018 ] Parser annotations for spirit X3
+//
+// I would like to thank Rainbowverse, llc (https://primeorbial.com/)
+// for sponsoring this work and donating it to the community.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our AST (employee and person structs)
+ ///////////////////////////////////////////////////////////////////////////
+ namespace x3 = boost::spirit::x3;
+
+ struct person : x3::position_tagged
+ {
+ person(
+ std::string const& first_name = ""
+ , std::string const& last_name = ""
+ )
+ : first_name(first_name)
+ , last_name(last_name)
+ {}
+
+ std::string first_name, last_name;
+ };
+
+ struct employee : x3::position_tagged
+ {
+ int age;
+ person who;
+ double salary;
+ };
+
+ using boost::fusion::operator<<;
+}}
+
+// We need to tell fusion about our employee struct
+// to make it a first-class fusion citizen. This has to
+// be in global scope.
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::person,
+ first_name, last_name
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::employee,
+ age, who, salary
+)
+
+namespace client
+{
+ namespace parser
+ {
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Our annotation handler
+ ///////////////////////////////////////////////////////////////////////
+
+ // tag used to get the position cache from the context
+ struct position_cache_tag;
+
+ struct annotate_position
+ {
+ template <typename T, typename Iterator, typename Context>
+ inline void on_success(Iterator const& first, Iterator const& last
+ , T& ast, Context const& context)
+ {
+ auto& position_cache = x3::get<position_cache_tag>(context).get();
+ position_cache.annotate(ast, first, last);
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // Our employee parser
+ ///////////////////////////////////////////////////////////////////////
+
+ using x3::int_;
+ using x3::double_;
+ using x3::lexeme;
+ using ascii::char_;
+
+ struct quoted_string_class;
+ struct person_class;
+ struct employee_class;
+
+ x3::rule<quoted_string_class, std::string> const quoted_string = "quoted_string";
+ x3::rule<person_class, ast::person> const person = "person";
+ x3::rule<employee_class, ast::employee> const employee = "employee";
+
+ auto const quoted_string_def = lexeme['"' >> +(char_ - '"') >> '"'];
+ auto const person_def = quoted_string >> ',' >> quoted_string;
+
+ auto const employee_def =
+ '{'
+ >> int_ >> ','
+ >> person >> ','
+ >> double_
+ >> '}'
+ ;
+
+ auto const employees = employee >> *(',' >> employee);
+
+ BOOST_SPIRIT_DEFINE(quoted_string, person, employee);
+
+ struct quoted_string_class {};
+ struct person_class : annotate_position {};
+ struct employee_class : annotate_position {};
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Our main parse entry point
+///////////////////////////////////////////////////////////////////////////////
+
+using iterator_type = std::string::const_iterator;
+using position_cache = boost::spirit::x3::position_cache<std::vector<iterator_type>>;
+
+std::vector<client::ast::employee>
+parse(std::string const& input, position_cache& positions)
+{
+ using boost::spirit::x3::ascii::space;
+
+ std::vector<client::ast::employee> ast;
+ iterator_type iter = input.begin();
+ iterator_type const end = input.end();
+
+ using boost::spirit::x3::with;
+
+ // Our parser
+ using client::parser::employees;
+ using client::parser::position_cache_tag;
+
+ auto const parser =
+ // we pass our position_cache to the parser so we can access
+ // it later in our on_sucess handlers
+ with<position_cache_tag>(std::ref(positions))
+ [
+ employees
+ ];
+
+ bool r = phrase_parse(iter, end, parser, space, ast);
+
+ 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";
+
+ for (auto const& emp : ast)
+ {
+ std::cout << "got: " << emp << std::endl;
+ }
+ std::cout << "\n-------------------------\n";
+
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ ast.clear();
+ }
+ return ast;
+}
+
+// Sample input:
+
+std::string input = R"(
+{
+ 23,
+ "Amanda",
+ "Stefanski",
+ 1000.99
+},
+{
+ 35,
+ "Angie",
+ "Chilcote",
+ 2000.99
+},
+{
+ 43,
+ "Dannie",
+ "Dillinger",
+ 3000.99
+},
+{
+ 22,
+ "Dorene",
+ "Dole",
+ 2500.99
+},
+{
+ 38,
+ "Rossana",
+ "Rafferty",
+ 5000.99
+}
+)";
+
+int
+main()
+{
+ position_cache positions{input.begin(), input.end()};
+ auto ast = parse(input, positions);
+
+ // Get the source of the 2nd employee and print it
+ auto pos = positions.position_of(ast[1]); // zero based of course!
+ std::cout << "Here's the 2nd employee:" << std::endl;
+ std::cout << std::string(pos.begin(), pos.end()) << std::endl;
+ std::cout << "-------------------------\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/attributes/tuple.cpp b/src/boost/libs/spirit/example/x3/attributes/tuple.cpp
new file mode 100644
index 00000000..979127a7
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/attributes/tuple.cpp
@@ -0,0 +1,51 @@
+
+/*=============================================================================
+ Copyright (c) 2019 Tom Tan
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include <boost/fusion/adapted/std_tuple.hpp>
+
+#include <iostream>
+#include <tuple>
+#include <string>
+
+//
+// X3 does not support more than one attribute anymore in the parse function,
+// this example show how to wrap multiple attributes into one leveraging std::tuple.
+//
+
+std::tuple<uint32_t, uint32_t, uint32_t> parse_message_prefix_revision(const std::string &s)
+{
+
+ namespace x3 = boost::spirit::x3;
+
+ auto const uint_3_digits = x3::uint_parser<std::uint32_t, 10, 3, 3>{};
+ auto const uint_4_digits = x3::uint_parser<std::uint32_t, 10, 4, 4>{};
+
+ auto iter = s.cbegin();
+ auto end_iter = s.cend();
+
+ std::tuple<uint32_t, uint32_t, uint32_t> length_id_revision;
+
+ x3::parse(iter, end_iter,
+ uint_4_digits >> uint_4_digits >> uint_3_digits,
+ length_id_revision);
+
+ return length_id_revision;
+}
+
+int main()
+{
+ std::string s = "00200060001";
+
+ std::cout << "parsing " << s << '\n';
+ auto [len, id, rev] = parse_message_prefix_revision(s);
+ std::cout << "length = " << len << '\n'
+ << "id = " << id << '\n'
+ << "revision =" << rev;
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/calc/calc1.cpp b/src/boost/libs/spirit/example/x3/calc/calc1.cpp
new file mode 100644
index 00000000..0a8e0c96
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc1.cpp
@@ -0,0 +1,123 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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 ] spirit 1
+// [ JDG March 4, 2007 ] spirit 2
+// [ JDG February 21, 2011 ] spirit 2.5
+// [ JDG June 6, 2014 ] spirit x3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <iostream>
+#include <string>
+#include <list>
+#include <numeric>
+
+namespace x3 = boost::spirit::x3;
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace calculator_grammar
+ {
+ using x3::uint_;
+ using x3::char_;
+
+ x3::rule<class expression> const expression("expression");
+ x3::rule<class term> const term("term");
+ x3::rule<class factor> const factor("factor");
+
+ auto const expression_def =
+ term
+ >> *( ('+' >> term)
+ | ('-' >> term)
+ )
+ ;
+
+ auto const term_def =
+ factor
+ >> *( ('*' >> factor)
+ | ('/' >> factor)
+ )
+ ;
+
+ auto const factor_def =
+ uint_
+ | '(' >> expression >> ')'
+ | ('-' >> factor)
+ | ('+' >> factor)
+ ;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , term
+ , factor
+ );
+
+ auto calculator = expression;
+ }
+
+ using calculator_grammar::calculator;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// 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;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ auto& calc = client::calculator; // Our grammar
+
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+ boost::spirit::x3::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc2.cpp b/src/boost/libs/spirit/example/x3/calc/calc2.cpp
new file mode 100644
index 00000000..6c0a2444
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc2.cpp
@@ -0,0 +1,139 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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 lambda functions. The parser prints code suitable for a stack
+// based virtual machine.
+//
+// [ JDG May 10, 2002 ] spirit 1
+// [ JDG March 4, 2007 ] spirit 2
+// [ JDG February 21, 2011 ] spirit 2.5
+// [ JDG June 6, 2014 ] spirit x3 (from qi calc2, but using lambda functions)
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <iostream>
+#include <string>
+#include <list>
+#include <numeric>
+
+namespace x3 = boost::spirit::x3;
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Semantic actions
+ ////////////////////////////////////////////////////////1///////////////////////
+ namespace
+ {
+ using x3::_attr;
+
+ auto do_int = [](auto& ctx) { std::cout << "push " << _attr(ctx) << std::endl; };
+ auto do_add = []{ std::cout << "add\n"; };
+ auto do_subt = []{ std::cout << "subtract\n"; };
+ auto do_mult = []{ std::cout << "mult\n"; };
+ auto do_div = []{ std::cout << "divide\n"; };
+ auto do_neg = []{ std::cout << "negate\n"; };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace calculator_grammar
+ {
+ using x3::uint_;
+ using x3::char_;
+
+ x3::rule<class expression> const expression("expression");
+ x3::rule<class term> const term("term");
+ x3::rule<class factor> const factor("factor");
+
+ auto const expression_def =
+ term
+ >> *( ('+' >> term [do_add])
+ | ('-' >> term [do_subt])
+ )
+ ;
+
+ auto const term_def =
+ factor
+ >> *( ('*' >> factor [do_mult])
+ | ('/' >> factor [do_div])
+ )
+ ;
+
+ auto const factor_def =
+ uint_ [do_int]
+ | '(' >> expression >> ')'
+ | ('-' >> factor [do_neg])
+ | ('+' >> factor)
+ ;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , term
+ , factor
+ );
+
+ auto calculator = expression;
+ }
+
+ using calculator_grammar::calculator;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// 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;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ auto& calc = client::calculator; // Our grammar
+
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+ boost::spirit::x3::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc4.cpp b/src/boost/libs/spirit/example/x3/calc/calc4.cpp
new file mode 100644
index 00000000..289e2cd9
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc4.cpp
@@ -0,0 +1,273 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST. The AST,
+// once created, is traversed, 1) To print its contents and
+// 2) To evaluate the result.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG January 9, 2013 ] Spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <iostream>
+#include <string>
+#include <list>
+#include <numeric>
+
+namespace x3 = boost::spirit::x3;
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct program;
+
+ struct operand : x3::variant<
+ nil
+ , unsigned int
+ , x3::forward_ast<signed_>
+ , x3::forward_ast<program>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct program
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
+ sign, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::program,
+ first, rest
+)
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST Printer
+ ///////////////////////////////////////////////////////////////////////////
+ struct printer
+ {
+ typedef void result_type;
+
+ void operator()(nil) const {}
+ void operator()(unsigned int n) const { std::cout << n; }
+
+ void operator()(operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': std::cout << " add"; break;
+ case '-': std::cout << " subt"; break;
+ case '*': std::cout << " mult"; break;
+ case '/': std::cout << " div"; break;
+ }
+ }
+
+ void operator()(signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': std::cout << " neg"; break;
+ case '+': std::cout << " pos"; break;
+ }
+ }
+
+ void operator()(program const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ for (operation const& oper: x.rest)
+ {
+ std::cout << ' ';
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST evaluator
+ ///////////////////////////////////////////////////////////////////////////
+ struct eval
+ {
+ typedef int result_type;
+
+ int operator()(nil) const { BOOST_ASSERT(0); return 0; }
+ int operator()(unsigned int n) const { return n; }
+
+ int operator()(int lhs, operation const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': return lhs + rhs;
+ case '-': return lhs - rhs;
+ case '*': return lhs * rhs;
+ case '/': return lhs / rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(signed_ const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': return -rhs;
+ case '+': return +rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(program const& x) const
+ {
+ return std::accumulate(
+ x.rest.begin(), x.rest.end()
+ , boost::apply_visitor(*this, x.first)
+ , *this);
+ }
+ };
+}}
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace calculator_grammar
+ {
+ using x3::uint_;
+ using x3::char_;
+
+ x3::rule<class expression, ast::program> const expression("expression");
+ x3::rule<class term, ast::program> const term("term");
+ x3::rule<class factor, ast::operand> const factor("factor");
+
+ auto const expression_def =
+ term
+ >> *( (char_('+') >> term)
+ | (char_('-') >> term)
+ )
+ ;
+
+ auto const term_def =
+ factor
+ >> *( (char_('*') >> factor)
+ | (char_('/') >> factor)
+ )
+ ;
+
+ auto const factor_def =
+ uint_
+ | '(' >> expression >> ')'
+ | (char_('-') >> factor)
+ | (char_('+') >> factor)
+ ;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , term
+ , factor
+ );
+
+ auto calculator = expression;
+ }
+
+ using calculator_grammar::calculator;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::ast::program ast_program;
+ typedef client::ast::printer ast_print;
+ typedef client::ast::eval ast_eval;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ auto& calc = client::calculator; // Our grammar
+ ast_program program; // Our program (AST)
+ ast_print print; // Prints the program
+ ast_eval eval; // Evaluates the program
+
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+ boost::spirit::x3::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, program);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ print(program);
+ std::cout << "\nResult: " << eval(program) << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc4b.cpp b/src/boost/libs/spirit/example/x3/calc/calc4b.cpp
new file mode 100644
index 00000000..176359ab
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc4b.cpp
@@ -0,0 +1,273 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST. The AST,
+// once created, is traversed, 1) To print its contents and
+// 2) To evaluate the result.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG January 9, 2013 ] Spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <iostream>
+#include <string>
+#include <list>
+#include <numeric>
+
+namespace x3 = boost::spirit::x3;
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct program;
+
+ struct operand : x3::variant<
+ nil
+ , unsigned int
+ , x3::forward_ast<signed_>
+ , x3::forward_ast<program>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct program
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
+ sign, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::program,
+ first, rest
+)
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST Printer
+ ///////////////////////////////////////////////////////////////////////////
+ struct printer
+ {
+ typedef void result_type;
+
+ void operator()(nil) const {}
+ void operator()(unsigned int n) const { std::cout << n; }
+
+ void operator()(operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': std::cout << " add"; break;
+ case '-': std::cout << " subt"; break;
+ case '*': std::cout << " mult"; break;
+ case '/': std::cout << " div"; break;
+ }
+ }
+
+ void operator()(signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': std::cout << " neg"; break;
+ case '+': std::cout << " pos"; break;
+ }
+ }
+
+ void operator()(program const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ for (operation const& oper: x.rest)
+ {
+ std::cout << ' ';
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST evaluator
+ ///////////////////////////////////////////////////////////////////////////
+ struct eval
+ {
+ typedef int result_type;
+
+ int operator()(nil) const { BOOST_ASSERT(0); return 0; }
+ int operator()(unsigned int n) const { return n; }
+
+ int operator()(int lhs, operation const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': return lhs + rhs;
+ case '-': return lhs - rhs;
+ case '*': return lhs * rhs;
+ case '/': return lhs / rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(signed_ const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': return -rhs;
+ case '+': return +rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(program const& x) const
+ {
+ return std::accumulate(
+ x.rest.begin(), x.rest.end()
+ , boost::apply_visitor(*this, x.first)
+ , *this);
+ }
+ };
+}}
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace calculator_grammar
+ {
+ using x3::uint_;
+ using x3::char_;
+
+ x3::rule<class expression, ast::program> const expression("expression");
+ x3::rule<class term, ast::program> const term("term");
+ x3::rule<class factor, ast::operand> const factor("factor");
+
+ auto const expression_def =
+ term
+ >> *( (char_('+') >> term)
+ | (char_('-') >> term)
+ )
+ ;
+
+ auto const term_def =
+ factor
+ >> *( (char_('*') >> factor)
+ | (char_('/') >> factor)
+ )
+ ;
+
+ auto const factor_def =
+ uint_
+ | '(' >> expression >> ')'
+ | (char_('-') >> factor)
+ | (char_('+') >> factor)
+ ;
+
+ BOOST_SPIRIT_DEFINE(expression, term, factor);
+
+ auto calculator = expression;
+ }
+
+ using calculator_grammar::calculator;
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::ast::program ast_program;
+ typedef client::ast::printer ast_print;
+ typedef client::ast::eval ast_eval;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ auto& calc = client::calculator; // Our grammar
+ ast_program program; // Our program (AST)
+ ast_print print; // Prints the program
+ ast_eval eval; // Evaluates the program
+
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+ boost::spirit::x3::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, program);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ print(program);
+ std::cout << "\nResult: " << eval(program) << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc4c/calc4c.cpp b/src/boost/libs/spirit/example/x3/calc/calc4c/calc4c.cpp
new file mode 100644
index 00000000..91d396b5
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc4c/calc4c.cpp
@@ -0,0 +1,77 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+ Copyright (c) 2013-2014 Agustin Berge
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST. The AST,
+// once created, is traversed, 1) To print its contents and
+// 2) To evaluate the result.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG January 9, 2013 ] Spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "grammar.hpp"
+
+#include <iostream>
+#include <string>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::ast::program ast_program;
+ typedef client::ast::printer ast_print;
+ typedef client::ast::eval ast_eval;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ auto& calc = client::calculator; // Our grammar
+ ast_program program; // Our program (AST)
+ ast_print print; // Prints the program
+ ast_eval eval; // Evaluates the program
+
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+ boost::spirit::x3::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, program);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ print(program);
+ std::cout << "\nResult: " << eval(program) << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \"" << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc4c/grammar.cpp b/src/boost/libs/spirit/example/x3/calc/calc4c/grammar.cpp
new file mode 100644
index 00000000..8d1526b2
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc4c/grammar.cpp
@@ -0,0 +1,68 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+ Copyright (c) 2013-2014 Agustin Berge
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST. The AST,
+// once created, is traversed, 1) To print its contents and
+// 2) To evaluate the result.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG January 9, 2013 ] Spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "grammar.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace calculator_grammar
+ {
+ using x3::uint_;
+ using x3::char_;
+
+ x3::rule<class expression, ast::program> const expression("expression");
+ x3::rule<class term, ast::program> const term("term");
+ x3::rule<class factor, ast::operand> const factor("factor");
+
+ auto const expression_def =
+ term
+ >> *( (char_('+') >> term)
+ | (char_('-') >> term)
+ )
+ ;
+
+ auto const term_def =
+ factor
+ >> *( (char_('*') >> factor)
+ | (char_('/') >> factor)
+ )
+ ;
+
+ auto const factor_def =
+ uint_
+ | '(' >> expression >> ')'
+ | (char_('-') >> factor)
+ | (char_('+') >> factor)
+ ;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , term
+ , factor
+ );
+
+ parser_type calculator()
+ {
+ return expression;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/calc/calc4c/grammar.hpp b/src/boost/libs/spirit/example/x3/calc/calc4c/grammar.hpp
new file mode 100644
index 00000000..89d867c6
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc4c/grammar.hpp
@@ -0,0 +1,192 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+ Copyright (c) 2013-2014 Agustin Berge
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// A Calculator example demonstrating generation of AST. The AST,
+// once created, is traversed, 1) To print its contents and
+// 2) To evaluate the result.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG January 9, 2013 ] Spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <list>
+#include <numeric>
+
+namespace x3 = boost::spirit::x3;
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct program;
+
+ typedef x3::variant<
+ nil
+ , unsigned int
+ , x3::forward_ast<signed_>
+ , x3::forward_ast<program>
+ >
+ operand;
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct program
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
+ sign, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::program,
+ first, rest
+)
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST Printer
+ ///////////////////////////////////////////////////////////////////////////
+ struct printer
+ {
+ typedef void result_type;
+
+ void operator()(nil) const {}
+ void operator()(unsigned int n) const { std::cout << n; }
+
+ void operator()(operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': std::cout << " add"; break;
+ case '-': std::cout << " subt"; break;
+ case '*': std::cout << " mult"; break;
+ case '/': std::cout << " div"; break;
+ }
+ }
+
+ void operator()(signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': std::cout << " neg"; break;
+ case '+': std::cout << " pos"; break;
+ }
+ }
+
+ void operator()(program const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ for (operation const& oper: x.rest)
+ {
+ std::cout << ' ';
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST evaluator
+ ///////////////////////////////////////////////////////////////////////////
+ struct eval
+ {
+ typedef int result_type;
+
+ int operator()(nil) const { BOOST_ASSERT(0); return 0; }
+ int operator()(unsigned int n) const { return n; }
+
+ int operator()(int lhs, operation const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': return lhs + rhs;
+ case '-': return lhs - rhs;
+ case '*': return lhs * rhs;
+ case '/': return lhs / rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(signed_ const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': return -rhs;
+ case '+': return +rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(program const& x) const
+ {
+ return std::accumulate( x.rest.begin(), x.rest.end()
+ , boost::apply_visitor(*this, x.first)
+ , *this);
+ }
+ };
+}}
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace calculator_grammar
+ {
+ using parser_type =
+ x3::any_parser<
+ std::string::const_iterator
+ , ast::program
+ , decltype(x3::make_context<x3::skipper_tag>(x3::ascii::space))
+ >;
+
+ parser_type calculator();
+ }
+
+ auto const calculator = calculator_grammar::calculator();
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc5.cpp b/src/boost/libs/spirit/example/x3/calc/calc5.cpp
new file mode 100644
index 00000000..f6cd6a63
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc5.cpp
@@ -0,0 +1,301 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Same as Calc4, this time, we'll incorporate debugging support,
+// plus error handling and reporting.
+//
+// [ JDG April 28, 2008 ] For BoostCon 2008
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG April 9, 2014 ] Spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+//#define BOOST_SPIRIT_X3_DEBUG
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <iostream>
+#include <string>
+#include <list>
+#include <numeric>
+
+namespace x3 = boost::spirit::x3;
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct program;
+
+ struct operand : x3::variant<
+ nil
+ , unsigned int
+ , x3::forward_ast<signed_>
+ , x3::forward_ast<program>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct program
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ // print function for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
+ sign, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::program,
+ first, rest
+)
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST Printer
+ ///////////////////////////////////////////////////////////////////////////
+ struct printer
+ {
+ typedef void result_type;
+
+ void operator()(nil) const {}
+ void operator()(unsigned int n) const { std::cout << n; }
+
+ void operator()(operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': std::cout << " add"; break;
+ case '-': std::cout << " subt"; break;
+ case '*': std::cout << " mult"; break;
+ case '/': std::cout << " div"; break;
+ }
+ }
+
+ void operator()(signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': std::cout << " neg"; break;
+ case '+': std::cout << " pos"; break;
+ }
+ }
+
+ void operator()(program const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ for (operation const& oper : x.rest)
+ {
+ std::cout << ' ';
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST evaluator
+ ///////////////////////////////////////////////////////////////////////////
+ struct eval
+ {
+ typedef int result_type;
+
+ int operator()(nil) const { BOOST_ASSERT(0); return 0; }
+ int operator()(unsigned int n) const { return n; }
+
+ int operator()(operation const& x, int lhs) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': return lhs + rhs;
+ case '-': return lhs - rhs;
+ case '*': return lhs * rhs;
+ case '/': return lhs / rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(signed_ const& x) const
+ {
+ int rhs = boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': return -rhs;
+ case '+': return +rhs;
+ }
+ BOOST_ASSERT(0);
+ return 0;
+ }
+
+ int operator()(program const& x) const
+ {
+ int state = boost::apply_visitor(*this, x.first);
+ for (operation const& oper : x.rest)
+ {
+ state = (*this)(oper, state);
+ }
+ return state;
+ }
+ };
+}}
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace calculator_grammar
+ {
+ using x3::uint_;
+ using x3::char_;
+
+ struct expression_class;
+ struct term_class;
+ struct factor_class;
+
+ x3::rule<expression_class, ast::program> const expression("expression");
+ x3::rule<term_class, ast::program> const term("term");
+ x3::rule<factor_class, ast::operand> const factor("factor");
+
+ auto const expression_def =
+ term
+ >> *( (char_('+') > term)
+ | (char_('-') > term)
+ )
+ ;
+
+ auto const term_def =
+ factor
+ >> *( (char_('*') > factor)
+ | (char_('/') > factor)
+ )
+ ;
+
+ auto const factor_def =
+ uint_
+ | '(' > expression > ')'
+ | (char_('-') > factor)
+ | (char_('+') > factor)
+ ;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , term
+ , factor
+ );
+
+ struct expression_class
+ {
+ // Our error handler
+ template <typename Iterator, typename Exception, typename Context>
+ x3::error_handler_result
+ on_error(Iterator&, Iterator const& last, Exception const& x, Context const& context)
+ {
+ std::cout
+ << "Error! Expecting: "
+ << x.which()
+ << " here: \""
+ << std::string(x.where(), last)
+ << "\""
+ << std::endl
+ ;
+ return x3::error_handler_result::fail;
+ }
+ };
+
+ auto calculator = expression;
+ }
+
+ using calculator_grammar::calculator;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::ast::program ast_program;
+ typedef client::ast::printer ast_print;
+ typedef client::ast::eval ast_eval;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ auto& calc = client::calculator; // Our grammar
+ ast_program program; // Our program (AST)
+ ast_print print; // Prints the program
+ ast_eval eval; // Evaluates the program
+
+ iterator_type iter = str.begin();
+ iterator_type end = str.end();
+ boost::spirit::x3::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, program);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ print(program);
+ std::cout << "\nResult: " << eval(program) << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc6.cpp b/src/boost/libs/spirit/example/x3/calc/calc6.cpp
new file mode 100644
index 00000000..f9554aa6
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc6.cpp
@@ -0,0 +1,341 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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 (and X3).
+//
+// [ JDG Sometime 2000 ] pre-boost
+// [ JDG September 18, 2002 ] spirit1
+// [ JDG April 8, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG April 9, 2014 ] Spirit X3 (from qi calc6)
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+//#define BOOST_SPIRIT_X3_DEBUG
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+
+#include <iostream>
+#include <string>
+#include <list>
+#include <numeric>
+
+namespace x3 = boost::spirit::x3;
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct expression;
+
+ struct operand : x3::variant<
+ nil
+ , unsigned int
+ , x3::forward_ast<signed_>
+ , x3::forward_ast<expression>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ // print function for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil) { out << "nil"; return out; }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
+ sign, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::expression,
+ first, rest
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+ op_int, // push constant integer into the stack
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ int top() const { return stack_ptr[-1]; };
+ void execute(std::vector<int> const& code);
+
+ private:
+
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+ };
+
+ void vmachine::execute(std::vector<int> const& code)
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+ stack_ptr = stack.begin();
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef void result_type;
+
+ std::vector<int>& code;
+ compiler(std::vector<int>& code)
+ : code(code) {}
+
+ void operator()(ast::nil) const { BOOST_ASSERT(0); }
+ void operator()(unsigned int n) const
+ {
+ code.push_back(op_int);
+ code.push_back(n);
+ }
+
+ void operator()(ast::operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': code.push_back(op_add); break;
+ case '-': code.push_back(op_sub); break;
+ case '*': code.push_back(op_mul); break;
+ case '/': code.push_back(op_div); break;
+ default: BOOST_ASSERT(0); break;
+ }
+ }
+
+ void operator()(ast::signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': code.push_back(op_neg); break;
+ case '+': break;
+ default: BOOST_ASSERT(0); break;
+ }
+ }
+
+ void operator()(ast::expression const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ for (ast::operation const& oper : x.rest)
+ {
+ (*this)(oper);
+ }
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The calculator grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace calculator_grammar
+ {
+ using x3::uint_;
+ using x3::char_;
+
+ struct expression_class;
+ struct term_class;
+ struct factor_class;
+
+ x3::rule<expression_class, ast::expression> const expression("expression");
+ x3::rule<term_class, ast::expression> const term("term");
+ x3::rule<factor_class, ast::operand> const factor("factor");
+
+ auto const expression_def =
+ term
+ >> *( (char_('+') > term)
+ | (char_('-') > term)
+ )
+ ;
+
+ auto const term_def =
+ factor
+ >> *( (char_('*') > factor)
+ | (char_('/') > factor)
+ )
+ ;
+
+ auto const factor_def =
+ uint_
+ | '(' > expression > ')'
+ | (char_('-') > factor)
+ | (char_('+') > factor)
+ ;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , term
+ , factor
+ );
+
+ struct expression_class
+ {
+ // Our error handler
+ template <typename Iterator, typename Exception, typename Context>
+ x3::error_handler_result
+ on_error(Iterator&, Iterator const& last, Exception const& x, Context const& context)
+ {
+ std::cout
+ << "Error! Expecting: "
+ << x.which()
+ << " here: \""
+ << std::string(x.where(), last)
+ << "\""
+ << std::endl
+ ;
+ return x3::error_handler_result::fail;
+ }
+ };
+
+ auto calculator = expression;
+ }
+
+ using calculator_grammar::calculator;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::ast::expression ast_expression;
+ typedef client::compiler compiler;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::vmachine mach; // Our virtual machine
+ std::vector<int> code; // Our VM code
+ auto& calc = client::calculator; // Our grammar
+ ast_expression expression; // Our program (AST)
+ compiler compile(code); // Compiles the program
+
+ iterator_type iter = str.begin();
+ iterator_type const end = str.end();
+ boost::spirit::x3::ascii::space_type space;
+ bool r = phrase_parse(iter, end, calc, space, expression);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ compile(expression);
+ mach.execute(code);
+ std::cout << "\nResult: " << mach.top() << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/ast.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/ast.hpp
new file mode 100644
index 00000000..600350ec
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/ast.hpp
@@ -0,0 +1,63 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC7_AST_HPP)
+#define BOOST_SPIRIT_X3_CALC7_AST_HPP
+
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ namespace x3 = boost::spirit::x3;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct nil {};
+ struct signed_;
+ struct expression;
+
+ struct operand : x3::variant<
+ nil
+ , unsigned int
+ , x3::forward_ast<signed_>
+ , x3::forward_ast<expression>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ // print function for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil";
+ return out;
+ }
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/ast_adapted.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/ast_adapted.hpp
new file mode 100644
index 00000000..bd56cfc7
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/ast_adapted.hpp
@@ -0,0 +1,25 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC7_AST_ADAPTED_HPP)
+#define BOOST_SPIRIT_X3_CALC7_AST_ADAPTED_HPP
+
+#include "ast.hpp"
+#include <boost/fusion/include/adapt_struct.hpp>
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
+ sign, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::expression,
+ first, rest
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/compiler.cpp b/src/boost/libs/spirit/example/x3/calc/calc7/compiler.cpp
new file mode 100644
index 00000000..8f6d6f09
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/compiler.cpp
@@ -0,0 +1,55 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "compiler.hpp"
+#include "vm.hpp"
+
+namespace client
+{
+ void compiler::operator()(ast::nil) const
+ {
+ BOOST_ASSERT(0);
+ }
+
+ void compiler::operator()(unsigned int n) const
+ {
+ code.push_back(op_int);
+ code.push_back(n);
+ }
+
+ void compiler::operator()(ast::operation const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.operator_)
+ {
+ case '+': code.push_back(op_add); break;
+ case '-': code.push_back(op_sub); break;
+ case '*': code.push_back(op_mul); break;
+ case '/': code.push_back(op_div); break;
+ default: BOOST_ASSERT(0); break;
+ }
+ }
+
+ void compiler::operator()(ast::signed_ const& x) const
+ {
+ boost::apply_visitor(*this, x.operand_);
+ switch (x.sign)
+ {
+ case '-': code.push_back(op_neg); break;
+ case '+': break;
+ default: BOOST_ASSERT(0); break;
+ }
+ }
+
+ void compiler::operator()(ast::expression const& x) const
+ {
+ boost::apply_visitor(*this, x.first);
+ for (ast::operation const& oper : x.rest)
+ {
+ (*this)(oper);
+ }
+ }
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/compiler.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/compiler.hpp
new file mode 100644
index 00000000..3cf0ed84
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/compiler.hpp
@@ -0,0 +1,33 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC7_COMPILER_HPP)
+#define BOOST_SPIRIT_X3_CALC7_COMPILER_HPP
+
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef void result_type;
+
+ std::vector<int>& code;
+ compiler(std::vector<int>& code)
+ : code(code) {}
+
+ void operator()(ast::nil) const;
+ void operator()(unsigned int n) const;
+ void operator()(ast::operation const& x) const;
+ void operator()(ast::signed_ const& x) const;
+ void operator()(ast::expression const& x) const;
+ };
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/error_handler.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/error_handler.hpp
new file mode 100644
index 00000000..9517220d
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/error_handler.hpp
@@ -0,0 +1,40 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC7_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_X3_CALC7_ERROR_HANDLER_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include <iostream>
+
+namespace client { namespace calculator_grammar
+{
+ ////////////////////////////////////////////////////////////////////////////
+ // Our error handler
+ ////////////////////////////////////////////////////////////////////////////
+ namespace x3 = boost::spirit::x3;
+
+ struct error_handler
+ {
+ // Our error handler
+ template <typename Iterator, typename Exception, typename Context>
+ x3::error_handler_result
+ on_error(Iterator&, Iterator const& last, Exception const& x, Context const& context)
+ {
+ std::cout
+ << "Error! Expecting: "
+ << x.which()
+ << " here: \""
+ << std::string(x.where(), last)
+ << "\""
+ << std::endl
+ ;
+ return x3::error_handler_result::fail;
+ }
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/expression.cpp b/src/boost/libs/spirit/example/x3/calc/calc7/expression.cpp
new file mode 100644
index 00000000..3dcb694e
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/expression.cpp
@@ -0,0 +1,15 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression_def.hpp"
+
+namespace client { namespace calculator_grammar
+{
+ typedef std::string::const_iterator iterator_type;
+ typedef x3::phrase_parse_context<x3::ascii::space_type>::type context_type;
+
+ BOOST_SPIRIT_INSTANTIATE(expression_type, iterator_type, context_type);
+}}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/expression.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/expression.hpp
new file mode 100644
index 00000000..93568eaf
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/expression.hpp
@@ -0,0 +1,26 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC7_EXPRESSION_HPP)
+#define BOOST_SPIRIT_X3_CALC7_EXPRESSION_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace calculator_grammar
+ {
+ struct expression_class;
+ typedef x3::rule<expression_class, ast::expression> expression_type;
+ BOOST_SPIRIT_DECLARE(expression_type);
+ }
+
+ calculator_grammar::expression_type expression();
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/expression_def.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/expression_def.hpp
new file mode 100644
index 00000000..dc73c288
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/expression_def.hpp
@@ -0,0 +1,71 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC7_EXPRESSION_DEF_HPP)
+#define BOOST_SPIRIT_X3_CALC7_EXPRESSION_DEF_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include "ast.hpp"
+#include "ast_adapted.hpp"
+#include "expression.hpp"
+#include "error_handler.hpp"
+
+namespace client { namespace calculator_grammar
+{
+ using x3::uint_;
+ using x3::char_;
+
+ struct expression_class;
+ struct term_class;
+ struct factor_class;
+
+ typedef x3::rule<expression_class, ast::expression> expression_type;
+ typedef x3::rule<term_class, ast::expression> term_type;
+ typedef x3::rule<factor_class, ast::operand> factor_type;
+
+ expression_type const expression = "expression";
+ term_type const term = "term";
+ factor_type const factor = "factor";
+
+ auto const expression_def =
+ term
+ >> *( (char_('+') > term)
+ | (char_('-') > term)
+ )
+ ;
+
+ auto const term_def =
+ factor
+ >> *( (char_('*') > factor)
+ | (char_('/') > factor)
+ )
+ ;
+
+ auto const factor_def =
+ uint_
+ | '(' > expression > ')'
+ | (char_('-') > factor)
+ | (char_('+') > factor)
+ ;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , term
+ , factor
+ );
+
+ struct expression_class : error_handler {};
+}}
+
+namespace client
+{
+ calculator_grammar::expression_type expression()
+ {
+ return calculator_grammar::expression;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/main.cpp b/src/boost/libs/spirit/example/x3/calc/calc7/main.cpp
new file mode 100644
index 00000000..5f71230d
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/main.cpp
@@ -0,0 +1,81 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Same as calc6, but this version also shows off grammar modularization.
+// Here you will see how expressions is built as a modular grammars.
+//
+// [ JDG Sometime 2000 ] pre-boost
+// [ JDG September 18, 2002 ] spirit1
+// [ JDG April 8, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG April 9, 2014 ] Spirit X3 (from qi calc6)
+// [ JDG May 2, 2014 ] Modular grammar using BOOST_SPIRIT_DEFINE.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ast.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include "expression.hpp"
+#include "error_handler.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Expression parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type an expression...or [q or Q] to quit\n\n";
+
+ typedef std::string::const_iterator iterator_type;
+ typedef client::ast::expression ast_expression;
+ typedef client::compiler compiler;
+
+ std::string str;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ using boost::spirit::x3::ascii::space;
+
+ client::vmachine mach; // Our virtual machine
+ std::vector<int> code; // Our VM code
+ auto calc = client::expression(); // grammar
+
+ ast_expression ast; // Our program (AST)
+ compiler compile(code); // Compiles the program
+
+ iterator_type iter = str.begin();
+ iterator_type const end = str.end();
+ bool r = phrase_parse(iter, end, calc, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ compile(ast);
+ mach.execute(code);
+ std::cout << "\nResult: " << mach.top() << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/vm.cpp b/src/boost/libs/spirit/example/x3/calc/calc7/vm.cpp
new file mode 100644
index 00000000..323d7217
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/vm.cpp
@@ -0,0 +1,50 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "vm.hpp"
+
+namespace client
+{
+ void vmachine::execute(std::vector<int> const& code)
+ {
+ std::vector<int>::const_iterator pc = code.begin();
+ 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;
+ }
+ }
+ }
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc7/vm.hpp b/src/boost/libs/spirit/example/x3/calc/calc7/vm.hpp
new file mode 100644
index 00000000..2836efd3
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc7/vm.hpp
@@ -0,0 +1,48 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC7_VM_HPP)
+#define BOOST_SPIRIT_X3_CALC7_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+ op_int, // push constant integer into the stack
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ int top() const { return stack_ptr[-1]; };
+ void execute(std::vector<int> const& code);
+
+ private:
+
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+ };
+
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/ast.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/ast.hpp
new file mode 100644
index 00000000..aacde561
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/ast.hpp
@@ -0,0 +1,98 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_AST_HPP)
+#define BOOST_SPIRIT_X3_CALC8_AST_HPP
+
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ namespace x3 = boost::spirit::x3;
+
+ struct nil {};
+ struct signed_;
+ struct expression;
+
+ struct variable : x3::position_tagged
+ {
+ variable(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ struct operand :
+ x3::variant<
+ nil
+ , unsigned int
+ , variable
+ , x3::forward_ast<signed_>
+ , x3::forward_ast<expression>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ struct signed_
+ {
+ char sign;
+ operand operand_;
+ };
+
+ struct operation : x3::position_tagged
+ {
+ char operator_;
+ operand operand_;
+ };
+
+ struct expression : x3::position_tagged
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment : x3::position_tagged
+ {
+ variable lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ assignment assign;
+ };
+
+ struct statement :
+ x3::variant<
+ variable_declaration
+ , assignment>
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ typedef std::list<statement> statement_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil";
+ return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, variable const& var)
+ {
+ out << var.name; return out;
+ }
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/ast_adapted.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/ast_adapted.hpp
new file mode 100644
index 00000000..ca776109
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/ast_adapted.hpp
@@ -0,0 +1,33 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_AST_ADAPTED_HPP)
+#define BOOST_SPIRIT_X3_CALC8_AST_ADAPTED_HPP
+
+#include "ast.hpp"
+#include <boost/fusion/include/adapt_struct.hpp>
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_,
+ sign, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::expression,
+ first, rest
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::variable_declaration,
+ assign
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::assignment,
+ lhs, rhs
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/common.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/common.hpp
new file mode 100644
index 00000000..0a559573
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/common.hpp
@@ -0,0 +1,28 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_COMMON_HPP)
+#define BOOST_SPIRIT_X3_CALC8_COMMON_HPP
+
+#include <boost/spirit/home/x3.hpp>
+
+namespace client { namespace parser
+{
+ using x3::raw;
+ using x3::lexeme;
+ using x3::alpha;
+ using x3::alnum;
+
+ struct identifier_class;
+ typedef x3::rule<identifier_class, std::string> identifier_type;
+ identifier_type const identifier = "identifier";
+
+ auto const identifier_def = raw[lexeme[(alpha | '_') >> *(alnum | '_')]];
+
+ BOOST_SPIRIT_DEFINE(identifier);
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/compiler.cpp b/src/boost/libs/spirit/example/x3/calc/calc8/compiler.cpp
new file mode 100644
index 00000000..6410a981
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/compiler.cpp
@@ -0,0 +1,217 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "compiler.hpp"
+#include "vm.hpp"
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <iostream>
+
+namespace client { namespace code_gen
+{
+ void program::op(int a)
+ {
+ code.push_back(a);
+ }
+
+ void program::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ }
+
+ void program::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ }
+
+ int const* program::find_var(std::string const& name) const
+ {
+ auto i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void program::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = int(n);
+ }
+
+ void program::print_variables(std::vector<int> const& stack) const
+ {
+ for (auto const& p : variables)
+ {
+ std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
+ }
+ }
+
+ void program::print_assembler() const
+ {
+ auto pc = code.begin();
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ for (pair const& p : variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << "local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ std::cout << "op_neg" << std::endl;
+ break;
+
+ case op_add:
+ std::cout << "op_add" << std::endl;
+ break;
+
+ case op_sub:
+ std::cout << "op_sub" << std::endl;
+ break;
+
+ case op_mul:
+ std::cout << "op_mul" << std::endl;
+ break;
+
+ case op_div:
+ std::cout << "op_div" << std::endl;
+ break;
+
+ case op_load:
+ std::cout << "op_load " << locals[*pc++] << std::endl;
+ break;
+
+ case op_store:
+ std::cout << "op_store " << locals[*pc++] << std::endl;
+ break;
+
+ case op_int:
+ std::cout << "op_int " << *pc++ << std::endl;
+ break;
+
+ case op_stk_adj:
+ std::cout << "op_stk_adj " << *pc++ << std::endl;
+ break;
+ }
+ }
+ }
+
+ bool compiler::operator()(unsigned int x) const
+ {
+ program.op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable const& x) const
+ {
+ int const* p = program.find_var(x.name);
+ if (p == 0)
+ {
+ error_handler(x, "Undeclared variable: " + x.name);
+ return false;
+ }
+ program.op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::operation const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case '+': program.op(op_add); break;
+ case '-': program.op(op_sub); break;
+ case '*': program.op(op_mul); break;
+ case '/': program.op(op_div); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::signed_ const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.sign)
+ {
+ case '-': program.op(op_neg); break;
+ case '+': break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ for (ast::operation const& oper : x.rest)
+ {
+ if (!(*this)(oper))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x) const
+ {
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = program.find_var(x.lhs.name);
+ if (p == 0)
+ {
+ error_handler(x.lhs, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ program.op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x) const
+ {
+ int const* p = program.find_var(x.assign.lhs.name);
+ if (p != 0)
+ {
+ error_handler(x.assign.lhs, "Duplicate variable: " + x.assign.lhs.name);
+ return false;
+ }
+ bool r = (*this)(x.assign.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ program.add_var(x.assign.lhs.name);
+ program.op(op_store, *program.find_var(x.assign.lhs.name));
+ }
+ return r;
+ }
+
+ bool compiler::operator()(ast::statement_list const& x) const
+ {
+ program.clear();
+
+ // op_stk_adj 0 for now. we'll know how many variables we'll have later
+ program.op(op_stk_adj, 0);
+ for (ast::statement const& s : x)
+ {
+ if (!boost::apply_visitor(*this, s))
+ {
+ program.clear();
+ return false;
+ }
+ }
+ program[1] = int(program.nvars()); // now store the actual number of variables
+ return true;
+ }
+}}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/compiler.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/compiler.hpp
new file mode 100644
index 00000000..509298c9
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/compiler.hpp
@@ -0,0 +1,80 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_X3_CALC8_COMPILER_HPP)
+#define BOOST_SPIRIT_X3_CALC8_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Program
+ ///////////////////////////////////////////////////////////////////////////
+ struct program
+ {
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[i]; }
+ int operator[](std::size_t i) const { return code[i]; }
+ void clear() { code.clear(); variables.clear(); }
+ std::vector<int> const& operator()() const { return code; }
+
+ std::size_t nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+
+ void print_variables(std::vector<int> const& stack) const;
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::vector<int> code;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ////////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+ typedef std::function<
+ void(x3::position_tagged, std::string const&)>
+ error_handler_type;
+
+ template <typename ErrorHandler>
+ compiler(
+ client::code_gen::program& program
+ , ErrorHandler const& error_handler)
+ : program(program)
+ , error_handler(
+ [&](x3::position_tagged pos, std::string const& msg)
+ { error_handler(pos, msg); }
+ )
+ {}
+
+ bool operator()(ast::nil) const { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x) const;
+ bool operator()(ast::variable const& x) const;
+ bool operator()(ast::operation const& x) const;
+ bool operator()(ast::signed_ const& x) const;
+ bool operator()(ast::expression const& x) const;
+ bool operator()(ast::assignment const& x) const;
+ bool operator()(ast::variable_declaration const& x) const;
+ bool operator()(ast::statement_list const& x) const;
+
+ client::code_gen::program& program;
+ error_handler_type error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/config.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/config.hpp
new file mode 100644
index 00000000..d6664564
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/config.hpp
@@ -0,0 +1,26 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_CONFIG_HPP)
+#define BOOST_SPIRIT_X3_CALC8_CONFIG_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include "error_handler.hpp"
+
+namespace client { namespace parser
+{
+ typedef std::string::const_iterator iterator_type;
+ typedef x3::phrase_parse_context<x3::ascii::space_type>::type phrase_context_type;
+ typedef error_handler<iterator_type> error_handler_type;
+
+ typedef x3::context<
+ error_handler_tag
+ , std::reference_wrapper<error_handler_type>
+ , phrase_context_type>
+ context_type;
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/error_handler.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/error_handler.hpp
new file mode 100644
index 00000000..25cb268c
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/error_handler.hpp
@@ -0,0 +1,44 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_X3_CALC8_ERROR_HANDLER_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include "expression.hpp"
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ namespace x3 = boost::spirit::x3;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Our error handler
+ ////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ using error_handler = x3::error_handler<Iterator>;
+
+ // tag used to get our error handler from the context
+ using error_handler_tag = x3::error_handler_tag;
+
+ struct error_handler_base
+ {
+ template <typename Iterator, typename Exception, typename Context>
+ x3::error_handler_result on_error(
+ Iterator& first, Iterator const& last
+ , Exception const& x, Context const& context)
+ {
+ std::string message = "Error! Expecting: " + x.which() + " here:";
+ auto& error_handler = x3::get<error_handler_tag>(context).get();
+ error_handler(x.where(), message);
+ return x3::error_handler_result::fail;
+ }
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/expression.cpp b/src/boost/libs/spirit/example/x3/calc/calc8/expression.cpp
new file mode 100644
index 00000000..e7463cd3
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/expression.cpp
@@ -0,0 +1,13 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression_def.hpp"
+#include "config.hpp"
+
+namespace client { namespace parser
+{
+ BOOST_SPIRIT_INSTANTIATE(expression_type, iterator_type, context_type);
+}}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/expression.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/expression.hpp
new file mode 100644
index 00000000..d619510c
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/expression.hpp
@@ -0,0 +1,26 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_EXPRESSION_HPP)
+#define BOOST_SPIRIT_X3_CALC8_EXPRESSION_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace parser
+ {
+ struct expression_class;
+ typedef x3::rule<expression_class, ast::expression> expression_type;
+ BOOST_SPIRIT_DECLARE(expression_type);
+ }
+
+ parser::expression_type const& expression();
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/expression_def.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/expression_def.hpp
new file mode 100644
index 00000000..fe9eaee9
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/expression_def.hpp
@@ -0,0 +1,91 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_EXPRESSION_DEF_HPP)
+#define BOOST_SPIRIT_X3_CALC8_EXPRESSION_DEF_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp>
+#include "ast.hpp"
+#include "ast_adapted.hpp"
+#include "expression.hpp"
+#include "common.hpp"
+#include "error_handler.hpp"
+
+namespace client { namespace parser
+{
+ using x3::uint_;
+ using x3::char_;
+ using x3::raw;
+ using x3::lexeme;
+ using namespace x3::ascii;
+
+ struct additive_expr_class;
+ struct multiplicative_expr_class;
+ struct unary_expr_class;
+ struct primary_expr_class;
+
+ typedef x3::rule<additive_expr_class, ast::expression> additive_expr_type;
+ typedef x3::rule<multiplicative_expr_class, ast::expression> multiplicative_expr_type;
+ typedef x3::rule<unary_expr_class, ast::operand> unary_expr_type;
+ typedef x3::rule<primary_expr_class, ast::operand> primary_expr_type;
+
+ expression_type const expression = "expression";
+ additive_expr_type const additive_expr = "additive_expr";
+ multiplicative_expr_type const multiplicative_expr = "multiplicative_expr";
+ unary_expr_type unary_expr = "unary_expr";
+ primary_expr_type primary_expr = "primary_expr";
+
+ auto const additive_expr_def =
+ multiplicative_expr
+ >> *( (char_('+') > multiplicative_expr)
+ | (char_('-') > multiplicative_expr)
+ )
+ ;
+
+ auto const multiplicative_expr_def =
+ unary_expr
+ >> *( (char_('*') > unary_expr)
+ | (char_('/') > unary_expr)
+ )
+ ;
+
+ auto const unary_expr_def =
+ primary_expr
+ | (char_('-') > primary_expr)
+ | (char_('+') > primary_expr)
+ ;
+
+ auto const primary_expr_def =
+ uint_
+ | identifier
+ | '(' > expression > ')'
+ ;
+
+ auto const expression_def = additive_expr;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , additive_expr
+ , multiplicative_expr
+ , unary_expr
+ , primary_expr
+ );
+
+ struct unary_expr_class : x3::annotate_on_success {};
+ struct primary_expr_class : x3::annotate_on_success {};
+
+}}
+
+namespace client
+{
+ parser::expression_type const& expression()
+ {
+ return parser::expression;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/main.cpp b/src/boost/libs/spirit/example/x3/calc/calc8/main.cpp
new file mode 100644
index 00000000..e87ccbb7
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/main.cpp
@@ -0,0 +1,114 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Now we'll introduce variables and assignment. This time, we'll also
+// be renaming some of the rules -- a strategy for a grander scheme
+// to come ;-)
+//
+// This version also shows off grammar modularization. Here you will
+// see how expressions and statements are built as modular grammars.
+//
+// [ JDG April 9, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG May 17, 2014 ] Ported from qi calc7 example.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ast.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "config.hpp"
+#include <iostream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Statement parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type some statements... ";
+ std::cout << "An empty line ends input, compiles, runs and prints results\n\n";
+ std::cout << "Example:\n\n";
+ std::cout << " var a = 123;\n";
+ std::cout << " var b = 456;\n";
+ std::cout << " var c = a + b * 2;\n\n";
+ std::cout << "-------------------------\n";
+
+ std::string str;
+ std::string source;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+ source += str + '\n';
+ }
+
+ using client::parser::iterator_type;
+ iterator_type iter(source.begin());
+ iterator_type end(source.end());
+
+ client::vmachine vm; // Our virtual machine
+ client::code_gen::program program; // Our VM program
+ client::ast::statement_list ast; // Our AST
+
+ using boost::spirit::x3::with;
+ using client::parser::error_handler_type;
+ using client::parser::error_handler_tag;
+ error_handler_type error_handler(iter, end, std::cerr); // Our error handler
+
+ // Our compiler
+ client::code_gen::compiler compile(program, error_handler);
+
+ // Our parser
+ auto const parser =
+ // we pass our error handler to the parser so we can access
+ // it later on in our on_error and on_sucess handlers
+ with<error_handler_tag>(std::ref(error_handler))
+ [
+ client::statement()
+ ];
+
+ using boost::spirit::x3::ascii::space;
+ bool success = phrase_parse(iter, end, parser, space, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compile(ast))
+ {
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ vm.execute(program());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ program.print_assembler();
+
+ std::cout << "-------------------------\n";
+ std::cout << "Results------------------\n\n";
+ program.print_variables(vm.get_stack());
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+
+ std::cout << "-------------------------\n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/statement.cpp b/src/boost/libs/spirit/example/x3/calc/calc8/statement.cpp
new file mode 100644
index 00000000..ec4bca61
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/statement.cpp
@@ -0,0 +1,13 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement_def.hpp"
+#include "config.hpp"
+
+namespace client { namespace parser
+{
+ BOOST_SPIRIT_INSTANTIATE(statement_type, iterator_type, context_type);
+}}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/statement.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/statement.hpp
new file mode 100644
index 00000000..7b8973d0
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/statement.hpp
@@ -0,0 +1,26 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_STATEMENT_HPP)
+#define BOOST_SPIRIT_X3_CALC8_STATEMENT_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace parser
+ {
+ struct statement_class;
+ typedef x3::rule<statement_class, ast::statement_list> statement_type;
+ BOOST_SPIRIT_DECLARE(statement_type);
+ }
+
+ parser::statement_type const& statement();
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/statement_def.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/statement_def.hpp
new file mode 100644
index 00000000..8772c76f
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/statement_def.hpp
@@ -0,0 +1,84 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_STATEMENT_DEF_HPP)
+#define BOOST_SPIRIT_X3_CALC8_STATEMENT_DEF_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp>
+#include "ast.hpp"
+#include "ast_adapted.hpp"
+#include "statement.hpp"
+#include "expression.hpp"
+#include "common.hpp"
+#include "error_handler.hpp"
+
+namespace client { namespace parser
+{
+ using x3::raw;
+ using x3::lexeme;
+ using namespace x3::ascii;
+
+ struct statement_list_class;
+ struct variable_declaration_class;
+ struct assignment_class;
+ struct variable_class;
+
+ typedef x3::rule<statement_list_class, ast::statement_list> statement_list_type;
+ typedef x3::rule<variable_declaration_class, ast::variable_declaration> variable_declaration_type;
+ typedef x3::rule<assignment_class, ast::assignment> assignment_type;
+ typedef x3::rule<variable_class, ast::variable> variable_type;
+
+ statement_type const statement = "statement";
+ statement_list_type const statement_list = "statement_list";
+ variable_declaration_type const variable_declaration = "variable_declaration";
+ assignment_type const assignment = "assignment";
+ variable_type const variable = "variable";
+
+ // Import the expression rule
+ namespace { auto const& expression = client::expression(); }
+
+ auto const statement_list_def =
+ +(variable_declaration | assignment)
+ ;
+
+ auto const variable_declaration_def =
+ lexeme["var" >> !(alnum | '_')] // make sure we have whole words
+ > assignment
+ ;
+
+ auto const assignment_def =
+ variable
+ > '='
+ > expression
+ > ';'
+ ;
+
+ auto const variable_def = identifier;
+ auto const statement_def = statement_list;
+
+ BOOST_SPIRIT_DEFINE(
+ statement
+ , statement_list
+ , variable_declaration
+ , assignment
+ , variable
+ );
+
+ struct statement_class : error_handler_base, x3::annotate_on_success {};
+ struct assignment_class : x3::annotate_on_success {};
+ struct variable_class : x3::annotate_on_success {};
+}}
+
+namespace client
+{
+ parser::statement_type const& statement()
+ {
+ return parser::statement;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/vm.cpp b/src/boost/libs/spirit/example/x3/calc/calc8/vm.cpp
new file mode 100644
index 00000000..ff6c8400
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/vm.cpp
@@ -0,0 +1,64 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "vm.hpp"
+
+namespace client
+{
+ void vmachine::execute(std::vector<int> const& code)
+ {
+ auto pc = code.begin();
+ auto locals = stack.begin();
+ stack_ptr = stack.begin();
+
+ while (pc != code.end())
+ {
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_load:
+ *stack_ptr++ = locals[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ locals[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_stk_adj:
+ stack_ptr = stack.begin() + *pc++;
+ break;
+ }
+ }
+ }
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc8/vm.hpp b/src/boost/libs/spirit/example/x3/calc/calc8/vm.hpp
new file mode 100644
index 00000000..29072977
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc8/vm.hpp
@@ -0,0 +1,51 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC8_VM_HPP)
+#define BOOST_SPIRIT_X3_CALC8_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ////////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ////////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+ op_int, // push constant integer into the stack
+ op_stk_adj // adjust the stack for local variables
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ , stack_ptr(stack.begin())
+ {
+ }
+
+ void execute(std::vector<int> const& code);
+ std::vector<int> const& get_stack() const { return stack; };
+
+ private:
+
+ std::vector<int> stack;
+ std::vector<int>::iterator stack_ptr;
+ };
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/ast.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/ast.hpp
new file mode 100644
index 00000000..b3e82c49
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/ast.hpp
@@ -0,0 +1,139 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_AST_HPP)
+#define BOOST_SPIRIT_X3_CALC9_AST_HPP
+
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ namespace x3 = boost::spirit::x3;
+
+ struct nil {};
+ struct unary;
+ struct expression;
+
+ struct variable : x3::position_tagged
+ {
+ variable(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ struct operand :
+ x3::variant<
+ nil
+ , unsigned int
+ , variable
+ , x3::forward_ast<unary>
+ , x3::forward_ast<expression>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ enum optoken
+ {
+ op_plus,
+ op_minus,
+ op_times,
+ op_divide,
+ op_positive,
+ op_negative,
+ op_not,
+ op_equal,
+ op_not_equal,
+ op_less,
+ op_less_equal,
+ op_greater,
+ op_greater_equal,
+ op_and,
+ op_or
+ };
+
+ struct unary
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct operation : x3::position_tagged
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct expression : x3::position_tagged
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment : x3::position_tagged
+ {
+ variable lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ assignment assign;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+
+ struct statement :
+ x3::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil";
+ return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, variable const& var)
+ {
+ out << var.name; return out;
+ }
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/ast_adapted.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/ast_adapted.hpp
new file mode 100644
index 00000000..3f8d3cb1
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/ast_adapted.hpp
@@ -0,0 +1,41 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_AST_ADAPTED_HPP)
+#define BOOST_SPIRIT_X3_CALC9_AST_ADAPTED_HPP
+
+#include "ast.hpp"
+#include <boost/fusion/include/adapt_struct.hpp>
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::unary,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::operation,
+ operator_, operand_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::expression,
+ first, rest
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::variable_declaration,
+ assign
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::assignment,
+ lhs, rhs
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::if_statement,
+ condition, then, else_
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::while_statement,
+ condition, body
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/common.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/common.hpp
new file mode 100644
index 00000000..1f1a7011
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/common.hpp
@@ -0,0 +1,28 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_COMMON_HPP)
+#define BOOST_SPIRIT_X3_CALC9_COMMON_HPP
+
+#include <boost/spirit/home/x3.hpp>
+
+namespace client { namespace parser
+{
+ using x3::raw;
+ using x3::lexeme;
+ using x3::alpha;
+ using x3::alnum;
+
+ struct identifier_class;
+ typedef x3::rule<identifier_class, std::string> identifier_type;
+ identifier_type const identifier = "identifier";
+
+ auto const identifier_def = raw[lexeme[(alpha | '_') >> *(alnum | '_')]];
+
+ BOOST_SPIRIT_DEFINE(identifier);
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/compiler.cpp b/src/boost/libs/spirit/example/x3/calc/calc9/compiler.cpp
new file mode 100644
index 00000000..620fa22d
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/compiler.cpp
@@ -0,0 +1,376 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "compiler.hpp"
+#include "vm.hpp"
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <iostream>
+#include <set>
+#include <iostream>
+
+namespace client { namespace code_gen
+{
+ void program::op(int a)
+ {
+ code.push_back(a);
+ }
+
+ void program::op(int a, int b)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ }
+
+ void program::op(int a, int b, int c)
+ {
+ code.push_back(a);
+ code.push_back(b);
+ code.push_back(c);
+ }
+
+ int const* program::find_var(std::string const& name) const
+ {
+ auto i = variables.find(name);
+ if (i == variables.end())
+ return 0;
+ return &i->second;
+ }
+
+ void program::add_var(std::string const& name)
+ {
+ std::size_t n = variables.size();
+ variables[name] = int(n);
+ }
+
+ void program::print_variables(std::vector<int> const& stack) const
+ {
+ for (auto const& p : variables)
+ {
+ std::cout << " " << p.first << ": " << stack[p.second] << std::endl;
+ }
+ }
+
+ void program::print_assembler() const
+ {
+ auto pc = code.begin();
+
+ std::vector<std::string> locals(variables.size());
+ typedef std::pair<std::string, int> pair;
+ for (pair const& p : variables)
+ {
+ locals[p.second] = p.first;
+ std::cout << "local "
+ << p.first << ", @" << p.second << std::endl;
+ }
+
+ std::map<std::size_t, std::string> lines;
+ std::set<std::size_t> jumps;
+
+ while (pc != code.end())
+ {
+ std::string line;
+ std::size_t address = pc - code.begin();
+
+ switch (*pc++)
+ {
+ case op_neg:
+ line += " op_neg";
+ break;
+
+ case op_not:
+ line += " op_not";
+ break;
+
+ case op_add:
+ line += " op_add";
+ break;
+
+ case op_sub:
+ line += " op_sub";
+ break;
+
+ case op_mul:
+ line += " op_mul";
+ break;
+
+ case op_div:
+ line += " op_div";
+ break;
+
+ case op_eq:
+ line += " op_eq";
+ break;
+
+ case op_neq:
+ line += " op_neq";
+ break;
+
+ case op_lt:
+ line += " op_lt";
+ break;
+
+ case op_lte:
+ line += " op_lte";
+ break;
+
+ case op_gt:
+ line += " op_gt";
+ break;
+
+ case op_gte:
+ line += " op_gte";
+ break;
+
+ case op_and:
+ line += " op_and";
+ break;
+
+ case op_or:
+ line += " op_or";
+ break;
+
+ case op_load:
+ line += " op_load ";
+ line += locals[*pc++];
+ break;
+
+ case op_store:
+ line += " op_store ";
+ line += locals[*pc++];
+ break;
+
+ case op_int:
+ line += " op_int ";
+ line += std::to_string(*pc++);
+ break;
+
+ case op_true:
+ line += " op_true";
+ break;
+
+ case op_false:
+ line += " op_false";
+ break;
+
+ case op_jump:
+ {
+ line += " op_jump ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += std::to_string(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_jump_if:
+ {
+ line += " op_jump_if ";
+ std::size_t pos = (pc - code.begin()) + *pc++;
+ if (pos == code.size())
+ line += "end";
+ else
+ line += std::to_string(pos);
+ jumps.insert(pos);
+ }
+ break;
+
+ case op_stk_adj:
+ line += " op_stk_adj ";
+ line += std::to_string(*pc++);
+ break;
+ }
+ lines[address] = line;
+ }
+
+ std::cout << "start:" << std::endl;
+ for (auto const& l : lines)
+ {
+ std::size_t pos = l.first;
+ if (jumps.find(pos) != jumps.end())
+ std::cout << pos << ':' << std::endl;
+ std::cout << l.second << std::endl;
+ }
+
+ std::cout << "end:" << std::endl;
+ }
+
+ bool compiler::operator()(unsigned int x) const
+ {
+ program.op(op_int, x);
+ return true;
+ }
+
+ bool compiler::operator()(bool x) const
+ {
+ program.op(x ? op_true : op_false);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable const& x) const
+ {
+ int const* p = program.find_var(x.name);
+ if (p == 0)
+ {
+ error_handler(x, "Undeclared variable: " + x.name);
+ return false;
+ }
+ program.op(op_load, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::operation const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_plus: program.op(op_add); break;
+ case ast::op_minus: program.op(op_sub); break;
+ case ast::op_times: program.op(op_mul); break;
+ case ast::op_divide: program.op(op_div); break;
+
+ case ast::op_equal: program.op(op_eq); break;
+ case ast::op_not_equal: program.op(op_neq); break;
+ case ast::op_less: program.op(op_lt); break;
+ case ast::op_less_equal: program.op(op_lte); break;
+ case ast::op_greater: program.op(op_gt); break;
+ case ast::op_greater_equal: program.op(op_gte); break;
+
+ case ast::op_and: program.op(op_and); break;
+ case ast::op_or: program.op(op_or); break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::unary const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.operand_))
+ return false;
+ switch (x.operator_)
+ {
+ case ast::op_negative: program.op(op_neg); break;
+ case ast::op_not: program.op(op_not); break;
+ case ast::op_positive: break;
+ default: BOOST_ASSERT(0); return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::expression const& x) const
+ {
+ if (!boost::apply_visitor(*this, x.first))
+ return false;
+ for (ast::operation const& oper : x.rest)
+ {
+ if (!(*this)(oper))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::assignment const& x) const
+ {
+ if (!(*this)(x.rhs))
+ return false;
+ int const* p = program.find_var(x.lhs.name);
+ if (p == 0)
+ {
+ error_handler(x.lhs, "Undeclared variable: " + x.lhs.name);
+ return false;
+ }
+ program.op(op_store, *p);
+ return true;
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x) const
+ {
+ int const* p = program.find_var(x.assign.lhs.name);
+ if (p != 0)
+ {
+ error_handler(x.assign.lhs, "Duplicate variable: " + x.assign.lhs.name);
+ return false;
+ }
+ bool r = (*this)(x.assign.rhs);
+ if (r) // don't add the variable if the RHS fails
+ {
+ program.add_var(x.assign.lhs.name);
+ program.op(op_store, *program.find_var(x.assign.lhs.name));
+ }
+ return r;
+ }
+
+ bool compiler::operator()(ast::statement const& x) const
+ {
+ return boost::apply_visitor(*this, x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x) const
+ {
+ for (auto const& s : x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x) const
+ {
+ if (!(*this)(x.condition))
+ return false;
+ program.op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t skip = program.size()-1; // mark its position
+ if (!(*this)(x.then))
+ return false;
+ program[skip] = int(program.size()-skip); // now we know where to jump to (after the if branch)
+
+ if (x.else_) // We got an alse
+ {
+ program[skip] += 2; // adjust for the "else" jump
+ program.op(op_jump, 0); // we shall fill this (0) in later
+ std::size_t exit = program.size()-1; // mark its position
+ if (!(*this)(*x.else_))
+ return false;
+ program[exit] = int(program.size()-exit); // now we know where to jump to (after the else branch)
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x) const
+ {
+ std::size_t loop = program.size(); // mark our position
+ if (!(*this)(x.condition))
+ return false;
+ program.op(op_jump_if, 0); // we shall fill this (0) in later
+ std::size_t exit = program.size()-1; // mark its position
+ if (!(*this)(x.body))
+ return false;
+ program.op(op_jump,
+ int(loop-1) - int(program.size())); // loop back
+ program[exit] = int(program.size()-exit); // now we know where to jump to (to exit the loop)
+ return true;
+ }
+
+ bool compiler::start(ast::statement_list const& x) const
+ {
+ program.clear();
+ // op_stk_adj 0 for now. we'll know how many variables we'll have later
+ program.op(op_stk_adj, 0);
+
+ if (!(*this)(x))
+ {
+ program.clear();
+ return false;
+ }
+ program[1] = int(program.nvars()); // now store the actual number of variables
+ return true;
+ }
+}}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/compiler.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/compiler.hpp
new file mode 100644
index 00000000..96b32a70
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/compiler.hpp
@@ -0,0 +1,87 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_COMPILER_HPP)
+#define BOOST_SPIRIT_X3_CALC9_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+#include <map>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Program
+ ///////////////////////////////////////////////////////////////////////////
+ struct program
+ {
+ void op(int a);
+ void op(int a, int b);
+ void op(int a, int b, int c);
+
+ int& operator[](std::size_t i) { return code[i]; }
+ int operator[](std::size_t i) const { return code[i]; }
+ void clear() { code.clear(); variables.clear(); }
+ std::size_t size() const { return code.size(); }
+ std::vector<int> const& operator()() const { return code; }
+
+ std::size_t nvars() const { return variables.size(); }
+ int const* find_var(std::string const& name) const;
+ void add_var(std::string const& name);
+
+ void print_variables(std::vector<int> const& stack) const;
+ void print_assembler() const;
+
+ private:
+
+ std::map<std::string, int> variables;
+ std::vector<int> code;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ////////////////////////////////////////////////////////////////////////////
+ struct compiler
+ {
+ typedef bool result_type;
+ typedef std::function<
+ void(x3::position_tagged, std::string const&)>
+ error_handler_type;
+
+ template <typename ErrorHandler>
+ compiler(
+ client::code_gen::program& program
+ , ErrorHandler const& error_handler)
+ : program(program)
+ , error_handler(
+ [&](x3::position_tagged pos, std::string const& msg)
+ { error_handler(pos, msg); }
+ )
+ {}
+
+ bool operator()(ast::nil) const { BOOST_ASSERT(0); return false; }
+ bool operator()(unsigned int x) const;
+ bool operator()(bool x) const;
+ bool operator()(ast::variable const& x) const;
+ bool operator()(ast::operation const& x) const;
+ bool operator()(ast::unary const& x) const;
+ bool operator()(ast::expression const& x) const;
+ bool operator()(ast::assignment const& x) const;
+ bool operator()(ast::variable_declaration const& x) const;
+ bool operator()(ast::statement_list const& x) const;
+ bool operator()(ast::statement const& x) const;
+ bool operator()(ast::if_statement const& x) const;
+ bool operator()(ast::while_statement const& x) const;
+
+ bool start(ast::statement_list const& x) const;
+
+ client::code_gen::program& program;
+ error_handler_type error_handler;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/config.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/config.hpp
new file mode 100644
index 00000000..a250bf72
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/config.hpp
@@ -0,0 +1,26 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_CONFIG_HPP)
+#define BOOST_SPIRIT_X3_CALC9_CONFIG_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include "error_handler.hpp"
+
+namespace client { namespace parser
+{
+ typedef std::string::const_iterator iterator_type;
+ typedef x3::phrase_parse_context<x3::ascii::space_type>::type phrase_context_type;
+ typedef error_handler<iterator_type> error_handler_type;
+
+ typedef x3::context<
+ error_handler_tag
+ , std::reference_wrapper<error_handler_type>
+ , phrase_context_type>
+ context_type;
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/error_handler.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/error_handler.hpp
new file mode 100644
index 00000000..8d4e8a65
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/error_handler.hpp
@@ -0,0 +1,44 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_X3_CALC9_ERROR_HANDLER_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include "expression.hpp"
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ namespace x3 = boost::spirit::x3;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Our error handler
+ ////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ using error_handler = x3::error_handler<Iterator>;
+
+ // tag used to get our error handler from the context
+ using error_handler_tag = x3::error_handler_tag;
+
+ struct error_handler_base
+ {
+ template <typename Iterator, typename Exception, typename Context>
+ x3::error_handler_result on_error(
+ Iterator& first, Iterator const& last
+ , Exception const& x, Context const& context)
+ {
+ std::string message = "Error! Expecting: " + x.which() + " here:";
+ auto& error_handler = x3::get<error_handler_tag>(context).get();
+ error_handler(x.where(), message);
+ return x3::error_handler_result::fail;
+ }
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/expression.cpp b/src/boost/libs/spirit/example/x3/calc/calc9/expression.cpp
new file mode 100644
index 00000000..e7463cd3
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/expression.cpp
@@ -0,0 +1,13 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression_def.hpp"
+#include "config.hpp"
+
+namespace client { namespace parser
+{
+ BOOST_SPIRIT_INSTANTIATE(expression_type, iterator_type, context_type);
+}}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/expression.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/expression.hpp
new file mode 100644
index 00000000..f9fa1cc3
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/expression.hpp
@@ -0,0 +1,26 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_EXPRESSION_HPP)
+#define BOOST_SPIRIT_X3_CALC9_EXPRESSION_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace parser
+ {
+ struct expression_class;
+ typedef x3::rule<expression_class, ast::expression> expression_type;
+ BOOST_SPIRIT_DECLARE(expression_type);
+ }
+
+ parser::expression_type const& expression();
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/expression_def.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/expression_def.hpp
new file mode 100644
index 00000000..251fb840
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/expression_def.hpp
@@ -0,0 +1,182 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_EXPRESSION_DEF_HPP)
+#define BOOST_SPIRIT_X3_CALC9_EXPRESSION_DEF_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp>
+#include "ast.hpp"
+#include "ast_adapted.hpp"
+#include "expression.hpp"
+#include "common.hpp"
+#include "error_handler.hpp"
+
+namespace client { namespace parser
+{
+ using x3::uint_;
+ using x3::char_;
+ using x3::bool_;
+ using x3::raw;
+ using x3::lexeme;
+ using namespace x3::ascii;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Tokens
+ ////////////////////////////////////////////////////////////////////////////
+
+ x3::symbols<ast::optoken> equality_op;
+ x3::symbols<ast::optoken> relational_op;
+ x3::symbols<ast::optoken> logical_op;
+ x3::symbols<ast::optoken> additive_op;
+ x3::symbols<ast::optoken> multiplicative_op;
+ x3::symbols<ast::optoken> unary_op;
+ x3::symbols<> keywords;
+
+ void add_keywords()
+ {
+ static bool once = false;
+ if (once)
+ return;
+ once = true;
+
+ logical_op.add
+ ("&&", ast::op_and)
+ ("||", ast::op_or)
+ ;
+
+ equality_op.add
+ ("==", ast::op_equal)
+ ("!=", ast::op_not_equal)
+ ;
+
+ relational_op.add
+ ("<", ast::op_less)
+ ("<=", ast::op_less_equal)
+ (">", ast::op_greater)
+ (">=", ast::op_greater_equal)
+ ;
+
+ additive_op.add
+ ("+", ast::op_plus)
+ ("-", ast::op_minus)
+ ;
+
+ multiplicative_op.add
+ ("*", ast::op_times)
+ ("/", ast::op_divide)
+ ;
+
+ unary_op.add
+ ("+", ast::op_positive)
+ ("-", ast::op_negative)
+ ("!", ast::op_not)
+ ;
+
+ keywords.add
+ ("var")
+ ("true")
+ ("false")
+ ("if")
+ ("else")
+ ("while")
+ ;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ ////////////////////////////////////////////////////////////////////////////
+
+ struct equality_expr_class;
+ struct relational_expr_class;
+ struct logical_expr_class;
+ struct additive_expr_class;
+ struct multiplicative_expr_class;
+ struct unary_expr_class;
+ struct primary_expr_class;
+
+ typedef x3::rule<equality_expr_class, ast::expression> equality_expr_type;
+ typedef x3::rule<relational_expr_class, ast::expression> relational_expr_type;
+ typedef x3::rule<logical_expr_class, ast::expression> logical_expr_type;
+ typedef x3::rule<additive_expr_class, ast::expression> additive_expr_type;
+ typedef x3::rule<multiplicative_expr_class, ast::expression> multiplicative_expr_type;
+ typedef x3::rule<unary_expr_class, ast::operand> unary_expr_type;
+ typedef x3::rule<primary_expr_class, ast::operand> primary_expr_type;
+
+ expression_type const expression = "expression";
+ equality_expr_type const equality_expr = "equality_expr";
+ relational_expr_type const relational_expr = "relational_expr";
+ logical_expr_type const logical_expr = "logical_expr";
+ additive_expr_type const additive_expr = "additive_expr";
+ multiplicative_expr_type const multiplicative_expr = "multiplicative_expr";
+ unary_expr_type const unary_expr = "unary_expr";
+ primary_expr_type const primary_expr = "primary_expr";
+
+ auto const logical_expr_def =
+ equality_expr
+ >> *(logical_op > equality_expr)
+ ;
+
+ auto const equality_expr_def =
+ relational_expr
+ >> *(equality_op > relational_expr)
+ ;
+
+ auto const relational_expr_def =
+ additive_expr
+ >> *(relational_op > additive_expr)
+ ;
+
+ auto const additive_expr_def =
+ multiplicative_expr
+ >> *(additive_op > multiplicative_expr)
+ ;
+
+ auto const multiplicative_expr_def =
+ unary_expr
+ >> *(multiplicative_op > unary_expr)
+ ;
+
+ auto const unary_expr_def =
+ primary_expr
+ | (unary_op > primary_expr)
+ ;
+
+ auto const primary_expr_def =
+ uint_
+ | bool_
+ | (!keywords >> identifier)
+ | '(' > expression > ')'
+ ;
+
+ auto const expression_def = logical_expr;
+
+ BOOST_SPIRIT_DEFINE(
+ expression
+ , logical_expr
+ , equality_expr
+ , relational_expr
+ , additive_expr
+ , multiplicative_expr
+ , unary_expr
+ , primary_expr
+ );
+
+ struct unary_expr_class : x3::annotate_on_success {};
+ struct primary_expr_class : x3::annotate_on_success {};
+
+}}
+
+namespace client
+{
+ parser::expression_type const& expression()
+ {
+ parser::add_keywords();
+ return parser::expression;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/main.cpp b/src/boost/libs/spirit/example/x3/calc/calc9/main.cpp
new file mode 100644
index 00000000..154860a3
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/main.cpp
@@ -0,0 +1,110 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Now we'll introduce boolean expressions and control structures.
+// Is it obvious now what we are up to? ;-)
+//
+// [ JDG April 9, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ JDG June 6, 2014 ] Ported from qi calc8 example.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ast.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "config.hpp"
+#include <iostream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Statement parser...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "Type some statements... ";
+ std::cout << "An empty line ends input, compiles, runs and prints results\n\n";
+ std::cout << "Example:\n\n";
+ std::cout << " var a = 123;\n";
+ std::cout << " var b = 456;\n";
+ std::cout << " var c = a + b * 2;\n\n";
+ std::cout << "-------------------------\n";
+
+ std::string str;
+ std::string source;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty())
+ break;
+ source += str + '\n';
+ }
+
+ using client::parser::iterator_type;
+ iterator_type iter(source.begin());
+ iterator_type end(source.end());
+
+
+ client::vmachine vm; // Our virtual machine
+ client::code_gen::program program; // Our VM program
+ client::ast::statement_list ast; // Our AST
+
+ using boost::spirit::x3::with;
+ using client::parser::error_handler_type;
+ error_handler_type error_handler(iter, end, std::cerr); // Our error handler
+
+ // Our compiler
+ client::code_gen::compiler compile(program, error_handler);
+
+ // Our parser
+ auto const parser =
+ // we pass our error handler to the parser so we can access
+ // it later on in our on_error and on_sucess handlers
+ with<client::parser::error_handler_tag>(std::ref(error_handler))
+ [
+ client::statement()
+ ];
+
+ using boost::spirit::x3::ascii::space;
+ bool success = phrase_parse(iter, end, parser, space, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compile.start(ast))
+ {
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ vm.execute(program());
+
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ program.print_assembler();
+
+ std::cout << "-------------------------\n";
+ std::cout << "Results------------------\n\n";
+ program.print_variables(vm.get_stack());
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+
+ std::cout << "-------------------------\n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/statement.cpp b/src/boost/libs/spirit/example/x3/calc/calc9/statement.cpp
new file mode 100644
index 00000000..ec4bca61
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/statement.cpp
@@ -0,0 +1,13 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "statement_def.hpp"
+#include "config.hpp"
+
+namespace client { namespace parser
+{
+ BOOST_SPIRIT_INSTANTIATE(statement_type, iterator_type, context_type);
+}}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/statement.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/statement.hpp
new file mode 100644
index 00000000..d0c3f514
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/statement.hpp
@@ -0,0 +1,27 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_STATEMENT_HPP)
+#define BOOST_SPIRIT_X3_CALC9_STATEMENT_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace parser
+ {
+ struct statement_class;
+ typedef x3::rule<statement_class, ast::statement_list> statement_type;
+ typedef statement_type::id statement_id;
+ BOOST_SPIRIT_DECLARE(statement_type);
+ }
+
+ parser::statement_type const& statement();
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/statement_def.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/statement_def.hpp
new file mode 100644
index 00000000..84355caa
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/statement_def.hpp
@@ -0,0 +1,84 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_STATEMENT_DEF_HPP)
+#define BOOST_SPIRIT_X3_CALC9_STATEMENT_DEF_HPP
+
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp>
+#include "ast.hpp"
+#include "ast_adapted.hpp"
+#include "statement.hpp"
+#include "expression.hpp"
+#include "common.hpp"
+#include "error_handler.hpp"
+
+namespace client { namespace parser
+{
+ using x3::raw;
+ using x3::lexeme;
+ using namespace x3::ascii;
+
+ struct statement_list_class;
+ struct variable_declaration_class;
+ struct assignment_class;
+ struct variable_class;
+
+ typedef x3::rule<statement_list_class, ast::statement_list> statement_list_type;
+ typedef x3::rule<variable_declaration_class, ast::variable_declaration> variable_declaration_type;
+ typedef x3::rule<assignment_class, ast::assignment> assignment_type;
+ typedef x3::rule<variable_class, ast::variable> variable_type;
+
+ statement_type const statement("statement");
+ statement_list_type const statement_list("statement_list");
+ variable_declaration_type const variable_declaration("variable_declaration");
+ assignment_type const assignment("assignment");
+ variable_type const variable("variable");
+
+ // Import the expression rule
+ namespace { auto const& expression = client::expression(); }
+
+ auto const statement_list_def =
+ +(variable_declaration | assignment)
+ ;
+
+ auto const variable_declaration_def =
+ lexeme["var" >> !(alnum | '_')] // make sure we have whole words
+ > assignment
+ ;
+
+ auto const assignment_def =
+ variable
+ > '='
+ > expression
+ > ';'
+ ;
+
+ auto const variable_def = identifier;
+ auto const statement_def = statement_list;
+
+ BOOST_SPIRIT_DEFINE(
+ statement
+ , statement_list
+ , variable_declaration
+ , assignment
+ , variable
+ );
+
+ struct statement_class : error_handler_base, x3::annotate_on_success {};
+ struct assignment_class : x3::annotate_on_success {};
+ struct variable_class : x3::annotate_on_success {};
+}}
+
+namespace client
+{
+ parser::statement_type const& statement()
+ {
+ return parser::statement;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/vm.cpp b/src/boost/libs/spirit/example/x3/calc/calc9/vm.cpp
new file mode 100644
index 00000000..d3c16713
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/vm.cpp
@@ -0,0 +1,156 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "vm.hpp"
+#include <boost/assert.hpp>
+
+namespace client
+{
+ int vmachine::execute(
+ std::vector<int> const& code
+ , std::vector<int>::const_iterator pc
+ , std::vector<int>::iterator frame_ptr
+ )
+ {
+ std::vector<int>::iterator stack_ptr = frame_ptr;
+
+ while (pc != code.end())
+ {
+ BOOST_ASSERT(pc != code.end());
+
+ switch (*pc++)
+ {
+ case op_neg:
+ stack_ptr[-1] = -stack_ptr[-1];
+ break;
+
+ case op_not:
+ stack_ptr[-1] = !bool(stack_ptr[-1]);
+ break;
+
+ case op_add:
+ --stack_ptr;
+ stack_ptr[-1] += stack_ptr[0];
+ break;
+
+ case op_sub:
+ --stack_ptr;
+ stack_ptr[-1] -= stack_ptr[0];
+ break;
+
+ case op_mul:
+ --stack_ptr;
+ stack_ptr[-1] *= stack_ptr[0];
+ break;
+
+ case op_div:
+ --stack_ptr;
+ stack_ptr[-1] /= stack_ptr[0];
+ break;
+
+ case op_eq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] == stack_ptr[0]);
+ break;
+
+ case op_neq:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] != stack_ptr[0]);
+ break;
+
+ case op_lt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] < stack_ptr[0]);
+ break;
+
+ case op_lte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] <= stack_ptr[0]);
+ break;
+
+ case op_gt:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] > stack_ptr[0]);
+ break;
+
+ case op_gte:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1] >= stack_ptr[0]);
+ break;
+
+ case op_and:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) && bool(stack_ptr[0]);
+ break;
+
+ case op_or:
+ --stack_ptr;
+ stack_ptr[-1] = bool(stack_ptr[-1]) || bool(stack_ptr[0]);
+ break;
+
+ case op_load:
+ *stack_ptr++ = frame_ptr[*pc++];
+ break;
+
+ case op_store:
+ --stack_ptr;
+ frame_ptr[*pc++] = stack_ptr[0];
+ break;
+
+ case op_int:
+ *stack_ptr++ = *pc++;
+ break;
+
+ case op_true:
+ *stack_ptr++ = true;
+ break;
+
+ case op_false:
+ *stack_ptr++ = false;
+ break;
+
+ case op_jump:
+ pc += *pc;
+ break;
+
+ case op_jump_if:
+ if (!bool(stack_ptr[-1]))
+ pc += *pc;
+ else
+ ++pc;
+ --stack_ptr;
+ break;
+
+ case op_stk_adj:
+ stack_ptr = stack.begin() + *pc++;
+ break;
+
+ case op_call:
+ {
+ int nargs = *pc++;
+ int jump = *pc++;
+
+ // a function call is a recursive call to execute
+ int r = execute(
+ code
+ , code.begin() + jump
+ , stack_ptr - nargs
+ );
+
+ // cleanup after return from function
+ stack_ptr[-nargs] = r; // get return value
+ stack_ptr -= (nargs - 1); // the stack will now contain
+ // the return value
+ }
+ break;
+
+ case op_return:
+ return stack_ptr[-1];
+ }
+ }
+ return -1;
+ }
+}
diff --git a/src/boost/libs/spirit/example/x3/calc/calc9/vm.hpp b/src/boost/libs/spirit/example/x3/calc/calc9/vm.hpp
new file mode 100644
index 00000000..345611cb
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/calc/calc9/vm.hpp
@@ -0,0 +1,81 @@
+/*=============================================================================
+ Copyright (c) 2001-2014 Joel de Guzman
+
+ Distributed under the 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_X3_CALC9_VM_HPP)
+#define BOOST_SPIRIT_X3_CALC9_VM_HPP
+
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine
+ ///////////////////////////////////////////////////////////////////////////
+ enum byte_code
+ {
+ op_neg, // negate the top stack entry
+ op_add, // add top two stack entries
+ op_sub, // subtract top two stack entries
+ op_mul, // multiply top two stack entries
+ op_div, // divide top two stack entries
+
+ op_not, // boolean negate the top stack entry
+ op_eq, // compare the top two stack entries for ==
+ op_neq, // compare the top two stack entries for !=
+ op_lt, // compare the top two stack entries for <
+ op_lte, // compare the top two stack entries for <=
+ op_gt, // compare the top two stack entries for >
+ op_gte, // compare the top two stack entries for >=
+
+ op_and, // logical and top two stack entries
+ op_or, // logical or top two stack entries
+
+ op_load, // load a variable
+ op_store, // store a variable
+
+ op_int, // push constant integer into the stack
+ op_true, // push constant 0 into the stack
+ op_false, // push constant 1 into the stack
+
+ op_jump_if, // jump to a relative position in the code if top stack
+ // evaluates to false
+ op_jump, // jump to a relative position in the code
+
+ op_stk_adj, // adjust the stack (for args and locals)
+ op_call, // function call
+ op_return // return from function
+ };
+
+ class vmachine
+ {
+ public:
+
+ vmachine(unsigned stackSize = 4096)
+ : stack(stackSize)
+ {
+ }
+
+ int execute(
+ std::vector<int> const& code // the program code
+ , std::vector<int>::const_iterator pc // program counter
+ , std::vector<int>::iterator frame_ptr // start of arguments and locals
+ );
+
+ int execute(std::vector<int> const& code)
+ {
+ return execute(code, code.begin(), stack.begin());
+ };
+
+ std::vector<int> const& get_stack() const { return stack; };
+
+ private:
+
+ std::vector<int> stack;
+ };
+}
+
+#endif
+
diff --git a/src/boost/libs/spirit/example/x3/complex_number.cpp b/src/boost/libs/spirit/example/x3/complex_number.cpp
new file mode 100644
index 00000000..3d63ab61
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/complex_number.cpp
@@ -0,0 +1,98 @@
+/*=============================================================================
+ Copyright (c) 2002-2015 Joel de Guzman
+
+ Distributed under the 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
+// [ JDG May 12, 2015 ] spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include <iostream>
+#include <string>
+#include <complex>
+
+///////////////////////////////////////////////////////////////////////////////
+// Our complex number parser/compiler
+///////////////////////////////////////////////////////////////////////////////
+namespace client
+{
+ template <typename Iterator>
+ bool parse_complex(Iterator first, Iterator last, std::complex<double>& c)
+ {
+ using boost::spirit::x3::double_;
+ using boost::spirit::x3::_attr;
+ using boost::spirit::x3::phrase_parse;
+ using boost::spirit::x3::ascii::space;
+
+ double rN = 0.0;
+ double iN = 0.0;
+ auto fr = [&](auto& ctx){ rN = _attr(ctx); };
+ auto fi = [&](auto& ctx){ iN = _attr(ctx); };
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ '(' >> double_[fr]
+ >> -(',' >> double_[fi]) >> ')'
+ | double_[fr]
+ ),
+ // End grammar
+
+ space);
+
+ if (!r || first != last) // fail if we did not get a full match
+ return false;
+ c = std::complex<double>(rN, iN);
+ return r;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA complex number micro parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a complex number of the form r or (r) or (r,i) \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::complex<double> c;
+ if (client::parse_complex(str.begin(), str.end(), c))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << c << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/employee.cpp b/src/boost/libs/spirit/example/x3/employee.cpp
new file mode 100644
index 00000000..62571027
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/employee.cpp
@@ -0,0 +1,134 @@
+/*=============================================================================
+ Copyright (c) 2002-2015 Joel de Guzman
+
+ Distributed under the 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 ]
+// [ JDG May 13, 2015 ] spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our employee struct
+ ///////////////////////////////////////////////////////////////////////////
+ struct employee
+ {
+ int age;
+ std::string forename;
+ std::string surname;
+ double salary;
+ };
+
+ using boost::fusion::operator<<;
+}}
+
+// We need to tell fusion about our employee struct
+// to make it a first-class fusion citizen. This has to
+// be in global scope.
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::employee,
+ age, forename, surname, salary
+)
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our employee parser
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace parser
+ {
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ using x3::int_;
+ using x3::lit;
+ using x3::double_;
+ using x3::lexeme;
+ using ascii::char_;
+
+ x3::rule<class employee, ast::employee> const employee = "employee";
+
+ auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"'];
+
+ auto const employee_def =
+ lit("employee")
+ >> '{'
+ >> int_ >> ','
+ >> quoted_string >> ','
+ >> quoted_string >> ','
+ >> double_
+ >> '}'
+ ;
+
+ BOOST_SPIRIT_DEFINE(employee);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+// 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, \"forename\", \"surname\", salary } \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ using boost::spirit::x3::ascii::space;
+ typedef std::string::const_iterator iterator_type;
+ using client::parser::employee;
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::ast::employee emp;
+ iterator_type iter = str.begin();
+ iterator_type const end = str.end();
+ bool r = phrase_parse(iter, end, employee, space, emp);
+
+ if (r && iter == end)
+ {
+ std::cout << boost::fusion::tuple_open('[');
+ std::cout << boost::fusion::tuple_close(']');
+ std::cout << boost::fusion::tuple_delimiter(", ");
+
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << emp << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/error_handling.cpp b/src/boost/libs/spirit/example/x3/error_handling.cpp
new file mode 100644
index 00000000..3b890a5e
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/error_handling.cpp
@@ -0,0 +1,277 @@
+/*=============================================================================
+ Copyright (c) 2002-2018 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Based on the employee parser (see employee.cpp), this example shows how
+// to implement error handling. This example also shows how to "inject" client
+// data, using the "with" directive, that the handlers can access.
+//
+// [ JDG May 9, 2007 ]
+// [ JDG May 13, 2015 ] spirit X3
+// [ JDG Feb 19, 2018 ] Error handling for spirit X3
+//
+// I would like to thank Rainbowverse, llc (https://primeorbial.com/)
+// for sponsoring this work and donating it to the community.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
+#include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our AST (employee and person structs)
+ ///////////////////////////////////////////////////////////////////////////
+ namespace x3 = boost::spirit::x3;
+
+ struct person : x3::position_tagged
+ {
+ person(
+ std::string const& first_name = ""
+ , std::string const& last_name = ""
+ )
+ : first_name(first_name)
+ , last_name(last_name)
+ {}
+
+ std::string first_name, last_name;
+ };
+
+ struct employee : x3::position_tagged
+ {
+ int age;
+ person who;
+ double salary;
+ };
+
+ using boost::fusion::operator<<;
+}}
+
+// We need to tell fusion about our employee struct
+// to make it a first-class fusion citizen. This has to
+// be in global scope.
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::person,
+ first_name, last_name
+)
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::employee,
+ age, who, salary
+)
+
+namespace client
+{
+ namespace parser
+ {
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Our error handler
+ ///////////////////////////////////////////////////////////////////////
+ struct error_handler
+ {
+ template <typename Iterator, typename Exception, typename Context>
+ x3::error_handler_result on_error(
+ Iterator& first, Iterator const& last
+ , Exception const& x, Context const& context)
+ {
+ auto& error_handler = x3::get<x3::error_handler_tag>(context).get();
+ std::string message = "Error! Expecting: " + x.which() + " here:";
+ error_handler(x.where(), message);
+ return x3::error_handler_result::fail;
+ }
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // Our employee parser
+ ///////////////////////////////////////////////////////////////////////
+
+ using x3::int_;
+ using x3::double_;
+ using x3::lexeme;
+ using ascii::char_;
+
+ struct quoted_string_class;
+ struct person_class;
+ struct employee_class;
+
+ x3::rule<quoted_string_class, std::string> const quoted_string = "quoted_string";
+ x3::rule<person_class, ast::person> const person = "person";
+ x3::rule<employee_class, ast::employee> const employee = "employee";
+
+ auto const quoted_string_def = lexeme['"' >> +(char_ - '"') >> '"'];
+ auto const person_def = quoted_string > ',' > quoted_string;
+
+ auto const employee_def =
+ '{'
+ > int_ > ','
+ > person > ','
+ > double_
+ > '}'
+ ;
+
+ auto const employees = employee >> *(',' >> employee);
+
+ BOOST_SPIRIT_DEFINE(quoted_string, person, employee);
+
+ struct quoted_string_class {};
+ struct person_class : x3::annotate_on_success {};
+ struct employee_class : error_handler, x3::annotate_on_success {};
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Our main parse entry point
+///////////////////////////////////////////////////////////////////////////////
+
+void parse(std::string const& input)
+{
+ using boost::spirit::x3::ascii::space;
+ typedef std::string::const_iterator iterator_type;
+
+ std::vector<client::ast::employee> ast;
+ iterator_type iter = input.begin();
+ iterator_type const end = input.end();
+
+ using boost::spirit::x3::with;
+ using boost::spirit::x3::error_handler_tag;
+ using error_handler_type = boost::spirit::x3::error_handler<iterator_type>;
+
+ // Our error handler
+ error_handler_type error_handler(iter, end, std::cerr);
+
+ // Our parser
+ using client::parser::employees;
+ auto const parser =
+ // we pass our error handler to the parser so we can access
+ // it later in our on_error and on_sucess handlers
+ with<error_handler_tag>(std::ref(error_handler))
+ [
+ employees
+ ];
+
+ bool r = phrase_parse(iter, end, parser, space, ast);
+
+ 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";
+
+ for (auto const& emp : ast)
+ {
+ std::cout << "got: " << emp << std::endl;
+ }
+ std::cout << "\n-------------------------\n";
+
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ ast.clear();
+ }
+}
+
+// Good sample:
+
+std::string good_input = R"(
+{
+ 23,
+ "Amanda",
+ "Stefanski",
+ 1000.99
+},
+{
+ 35,
+ "Angie",
+ "Chilcote",
+ 2000.99
+},
+{
+ 43,
+ "Dannie",
+ "Dillinger",
+ 3000.99
+},
+{
+ 22,
+ "Dorene",
+ "Dole",
+ 2500.99
+},
+{
+ 38,
+ "Rossana",
+ "Rafferty",
+ 5000.99
+}
+)";
+
+// Input sample with error:
+
+std::string bad_input = R"(
+{
+ 23,
+ "Amanda",
+ "Stefanski",
+ 1000.99
+},
+{
+ 35,
+ "Angie",
+ "Chilcote",
+ 2000.99
+},
+{
+ 43,
+ 'I am not a person!' <--- this should be a person
+ 3000.99
+},
+{
+ 22,
+ "Dorene",
+ "Dole",
+ 2500.99
+},
+{
+ 38,
+ "Rossana",
+ "Rafferty",
+ 5000.99
+}
+)";
+
+int
+main()
+{
+ // Good input
+ parse(good_input);
+
+ // Bad input
+ std::cout << "Now we have some errors" << std::endl;
+ parse(bad_input);
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/minimal/ast.hpp b/src/boost/libs/spirit/example/x3/minimal/ast.hpp
new file mode 100644
index 00000000..b66bb072
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/minimal/ast.hpp
@@ -0,0 +1,31 @@
+/*=============================================================================
+ Copyright (c) 2002-2018 Joel de Guzman
+
+ Distributed under the 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_X3_MINIMAL_AST_HPP)
+#define BOOST_SPIRIT_X3_MINIMAL_AST_HPP
+
+#include <boost/fusion/include/io.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Our employee AST struct
+ ///////////////////////////////////////////////////////////////////////////
+ struct employee
+ {
+ int age;
+ std::string forename;
+ std::string surname;
+ double salary;
+ };
+
+ using boost::fusion::operator<<;
+}}
+
+#endif \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/minimal/ast_adapted.hpp b/src/boost/libs/spirit/example/x3/minimal/ast_adapted.hpp
new file mode 100644
index 00000000..9d6c6fe9
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/minimal/ast_adapted.hpp
@@ -0,0 +1,21 @@
+/*=============================================================================
+ Copyright (c) 2002-2018 Joel de Guzman
+
+ Distributed under the 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_X3_MINIMAL_AST_ADAPTED_HPP)
+#define BOOST_SPIRIT_X3_MINIMAL_AST_ADAPTED_HPP
+
+#include <boost/fusion/include/adapt_struct.hpp>
+#include "ast.hpp"
+
+// We need to tell fusion about our employee struct
+// to make it a first-class fusion citizen. This has to
+// be in global scope.
+
+BOOST_FUSION_ADAPT_STRUCT(client::ast::employee,
+ age, forename, surname, salary
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/minimal/config.hpp b/src/boost/libs/spirit/example/x3/minimal/config.hpp
new file mode 100644
index 00000000..3787346a
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/minimal/config.hpp
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2018 Joel de Guzman
+
+ Distributed under the 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_X3_MINIMAL_CONFIG_HPP)
+#define BOOST_SPIRIT_X3_MINIMAL_CONFIG_HPP
+
+#include <boost/spirit/home/x3.hpp>
+
+namespace client { namespace parser
+{
+ namespace x3 = boost::spirit::x3;
+
+ using iterator_type = std::string::const_iterator;
+ using context_type = x3::phrase_parse_context<x3::ascii::space_type>::type;
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/minimal/employee.cpp b/src/boost/libs/spirit/example/x3/minimal/employee.cpp
new file mode 100644
index 00000000..8b2fa6c1
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/minimal/employee.cpp
@@ -0,0 +1,13 @@
+/*=============================================================================
+ Copyright (c) 2001-2018 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "employee_def.hpp"
+#include "config.hpp"
+
+namespace client { namespace parser
+{
+ BOOST_SPIRIT_INSTANTIATE(employee_type, iterator_type, context_type);
+}}
diff --git a/src/boost/libs/spirit/example/x3/minimal/employee.hpp b/src/boost/libs/spirit/example/x3/minimal/employee.hpp
new file mode 100644
index 00000000..a4475ec2
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/minimal/employee.hpp
@@ -0,0 +1,30 @@
+/*=============================================================================
+ Copyright (c) 2002-2018 Joel de Guzman
+
+ Distributed under the 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_X3_MINIMAL_EMPLOYEE_HPP)
+#define BOOST_SPIRIT_X3_MINIMAL_EMPLOYEE_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our employee parser declaration
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace parser
+ {
+ namespace x3 = boost::spirit::x3;
+ using employee_type = x3::rule<class employee, ast::employee>;
+ BOOST_SPIRIT_DECLARE(employee_type);
+ }
+
+ parser::employee_type employee();
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/minimal/employee_def.hpp b/src/boost/libs/spirit/example/x3/minimal/employee_def.hpp
new file mode 100644
index 00000000..227b2f7f
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/minimal/employee_def.hpp
@@ -0,0 +1,56 @@
+/*=============================================================================
+ Copyright (c) 2002-2018 Joel de Guzman
+
+ Distributed under the 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_X3_MINIMAL_EMPLOYEE_DEF_HPP)
+#define BOOST_SPIRIT_X3_MINIMAL_EMPLOYEE_DEF_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include "ast.hpp"
+#include "ast_adapted.hpp"
+#include "employee.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // Our employee parser definition
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace parser
+ {
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ using x3::int_;
+ using x3::lit;
+ using x3::double_;
+ using x3::lexeme;
+ using ascii::char_;
+
+ x3::rule<class employee, ast::employee> const employee = "employee";
+
+ auto const quoted_string = lexeme['"' >> +(char_ - '"') >> '"'];
+
+ auto const employee_def =
+ lit("employee")
+ >> '{'
+ >> int_ >> ','
+ >> quoted_string >> ','
+ >> quoted_string >> ','
+ >> double_
+ >> '}'
+ ;
+
+ BOOST_SPIRIT_DEFINE(employee);
+ }
+
+ parser::employee_type employee()
+ {
+ return parser::employee;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/minimal/main.cpp b/src/boost/libs/spirit/example/x3/minimal/main.cpp
new file mode 100644
index 00000000..aeb3bc51
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/minimal/main.cpp
@@ -0,0 +1,79 @@
+/*=============================================================================
+ Copyright (c) 2002-2018 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This is the same employee parser (see employee.cpp) but structured to
+// allow separate compilation of the actual parser in its own definition
+// file (employee_def.hpp) and cpp file (employee.cpp). This main cpp file
+// sees only the header file (employee.hpp). This is a good example on how
+// parsers are structured in a C++ application.
+//
+// [ JDG May 9, 2007 ]
+// [ JDG May 13, 2015 ] spirit X3
+// [ JDG Feb 20, 2018 ] Minimal "best practice" example
+//
+// I would like to thank Rainbowverse, llc (https://primeorbial.com/)
+// for sponsoring this work and donating it to the community.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include "ast.hpp"
+#include "ast_adapted.hpp"
+#include "employee.hpp"
+
+///////////////////////////////////////////////////////////////////////////////
+// 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, \"forename\", \"surname\", salary } \n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ using boost::spirit::x3::ascii::space;
+ using iterator_type = std::string::const_iterator;
+ using client::employee;
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ client::ast::employee emp;
+ iterator_type iter = str.begin();
+ iterator_type const end = str.end();
+ bool r = phrase_parse(iter, end, employee(), space, emp);
+
+ if (r && iter == end)
+ {
+ std::cout << boost::fusion::tuple_open('[');
+ std::cout << boost::fusion::tuple_close(']');
+ std::cout << boost::fusion::tuple_delimiter(", ");
+
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "got: " << emp << std::endl;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/num_list/num_list1.cpp b/src/boost/libs/spirit/example/x3/num_list/num_list1.cpp
new file mode 100644
index 00000000..34371e67
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/num_list/num_list1.cpp
@@ -0,0 +1,87 @@
+/*=============================================================================
+ Copyright (c) 2002-2015 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// This sample demontrates a parser for a comma separated list of numbers.
+// No semantic actions.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+// [ JDG May 12, 2015 ] spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list parser
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last)
+ {
+ using x3::double_;
+ using x3::phrase_parse;
+ using ascii::space;
+
+ bool r = phrase_parse(
+ first, // Start Iterator
+ last, // End Iterator
+ double_ >> *(',' >> double_), // The Parser
+ space // The Skip-Parser
+ );
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ if (client::parse_numbers(str.begin(), str.end()))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/num_list/num_list2.cpp b/src/boost/libs/spirit/example/x3/num_list/num_list2.cpp
new file mode 100644
index 00000000..67a75053
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/num_list/num_list2.cpp
@@ -0,0 +1,101 @@
+/*=============================================================================
+ Copyright (c) 2002-2015 Joel de Guzman
+
+ Distributed under the 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.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+// [ JDG May 12, 2015 ] spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using x3::double_;
+ using x3::phrase_parse;
+ using x3::_attr;
+ using ascii::space;
+
+ auto push_back = [&](auto& ctx){ v.push_back(_attr(ctx)); };
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[push_back] >> *(',' >> double_[push_back])
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/num_list/num_list3.cpp b/src/boost/libs/spirit/example/x3/num_list/num_list3.cpp
new file mode 100644
index 00000000..53a275bb
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/num_list/num_list3.cpp
@@ -0,0 +1,101 @@
+/*=============================================================================
+ Copyright (c) 2002-2015 Joel de Guzman
+
+ Distributed under the 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.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+// [ JDG May 12, 2015 ] spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using x3::double_;
+ using x3::phrase_parse;
+ using x3::_attr;
+ using ascii::space;
+
+ auto push_back = [&](auto& ctx){ v.push_back(_attr(ctx)); };
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[push_back] % ','
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/num_list/num_list4.cpp b/src/boost/libs/spirit/example/x3/num_list/num_list4.cpp
new file mode 100644
index 00000000..1c88b284
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/num_list/num_list4.cpp
@@ -0,0 +1,103 @@
+/*=============================================================================
+ Copyright (c) 2002-2015 Joel de Guzman
+
+ Distributed under the 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.
+// This time, the numbers are automatically collected into the attribute by
+// the parser itself using the full power of attribute grammars.
+//
+// [ JDG May 10, 2002 ] spirit1
+// [ JDG March 24, 2007 ] spirit2
+// [ JDG May 12, 2015 ] spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our number list compiler
+ ///////////////////////////////////////////////////////////////////////////
+ //[tutorial_numlist4
+ template <typename Iterator>
+ bool parse_numbers(Iterator first, Iterator last, std::vector<double>& v)
+ {
+ using x3::double_;
+ using x3::phrase_parse;
+ using x3::_attr;
+ using ascii::space;
+
+ bool r = phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_ % ','
+ )
+ ,
+ // End grammar
+
+ space, v);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+ //]
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA comma separated list parser for Spirit...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers will be inserted in a vector of numbers\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ std::vector<double> v;
+ if (client::parse_numbers(str.begin(), str.end(), v))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ for (std::vector<double>::size_type i = 0; i < v.size(); ++i)
+ std::cout << i << ": " << v[i] << std::endl;
+
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_examples/a.rexpr b/src/boost/libs/spirit/example/x3/rexpr/rexpr_examples/a.rexpr
new file mode 100644
index 00000000..880f5bac
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_examples/a.rexpr
@@ -0,0 +1,8 @@
+{
+ "color" = "blue"
+ "size" = "29 cm."
+ "position" = {
+ "x" = "123"
+ "y" = "456"
+ }
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/Jamfile b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/Jamfile
new file mode 100644
index 00000000..5723b1ed
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/Jamfile
@@ -0,0 +1,20 @@
+#
+# Copyright (C) 2015 Michael Caisse, ciere.com
+#
+# Distributed under the 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-x3-example-rexpr
+ : requirements
+ <c++-template-depth>512
+ <use>/boost//headers
+ <define>BOOST_SPIRIT_X3_NO_FILESYSTEM
+ <include>.
+ ;
+
+lib rexpr
+ : [ glob src/*.cpp ]
+ ;
+
+build-project test ;
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/ast.hpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/ast.hpp
new file mode 100644
index 00000000..c7635b12
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/ast.hpp
@@ -0,0 +1,42 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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_X3_REPR_AST_HPP)
+#define BOOST_SPIRIT_X3_REPR_AST_HPP
+
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+
+#include <map>
+
+namespace rexpr { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ namespace x3 = boost::spirit::x3;
+
+ struct rexpr;
+
+ struct rexpr_value : x3::variant<
+ std::string
+ , x3::forward_ast<rexpr>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ typedef std::map<std::string, rexpr_value> rexpr_map;
+ typedef std::pair<std::string, rexpr_value> rexpr_key_value;
+
+ struct rexpr : x3::position_tagged
+ {
+ rexpr_map entries;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/ast_adapted.hpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/ast_adapted.hpp
new file mode 100644
index 00000000..d325cbbd
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/ast_adapted.hpp
@@ -0,0 +1,22 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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_X3_REPR_AST_ADAPTED_HPP)
+#define BOOST_SPIRIT_X3_REPR_AST_ADAPTED_HPP
+
+#include "ast.hpp"
+
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+
+// We need to tell fusion about our rexpr and rexpr_key_value
+// to make them a first-class fusion citizens
+
+BOOST_FUSION_ADAPT_STRUCT(rexpr::ast::rexpr,
+ entries
+)
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/config.hpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/config.hpp
new file mode 100644
index 00000000..12a25def
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/config.hpp
@@ -0,0 +1,35 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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_X3_REPR_CONFIG_HPP)
+#define BOOST_SPIRIT_X3_REPR_CONFIG_HPP
+
+#include "error_handler.hpp"
+
+#include <boost/spirit/home/x3.hpp>
+
+namespace rexpr { namespace parser
+{
+ // Our Iterator Type
+ typedef std::string::const_iterator iterator_type;
+
+ // The Phrase Parse Context
+ typedef
+ x3::phrase_parse_context<x3::ascii::space_type>::type
+ phrase_context_type;
+
+ // Our Error Handler
+ typedef error_handler<iterator_type> error_handler_type;
+
+ // Combined Error Handler and Phrase Parse Context
+ typedef x3::context<
+ error_handler_tag
+ , std::reference_wrapper<error_handler_type>
+ , phrase_context_type>
+ context_type;
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/error_handler.hpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/error_handler.hpp
new file mode 100644
index 00000000..a173d492
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/error_handler.hpp
@@ -0,0 +1,72 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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_X3_REPR_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_X3_REPR_ERROR_HANDLER_HPP
+
+#include "rexpr.hpp"
+
+#include <boost/spirit/home/x3/support/ast/position_tagged.hpp>
+#include <boost/spirit/home/x3/support/utility/error_reporting.hpp>
+
+#include <map>
+
+namespace rexpr { namespace parser
+{
+ namespace x3 = boost::spirit::x3;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Our error handler
+ ////////////////////////////////////////////////////////////////////////////
+ // X3 Error Handler Utility
+ template <typename Iterator>
+ using error_handler = x3::error_handler<Iterator>;
+
+ // tag used to get our error handler from the context
+ using error_handler_tag = x3::error_handler_tag;
+
+ struct error_handler_base
+ {
+ error_handler_base();
+
+ template <typename Iterator, typename Exception, typename Context>
+ x3::error_handler_result on_error(
+ Iterator& first, Iterator const& last
+ , Exception const& x, Context const& context);
+
+ std::map<std::string, std::string> id_map;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Implementation
+ ////////////////////////////////////////////////////////////////////////////
+
+ inline error_handler_base::error_handler_base()
+ {
+ id_map["rexpr"] = "RExpression";
+ id_map["rexpr_value"] = "Value";
+ id_map["rexpr_key_value"] = "Key value pair";
+ }
+
+ template <typename Iterator, typename Exception, typename Context>
+ inline x3::error_handler_result
+ error_handler_base::on_error(
+ Iterator& first, Iterator const& last
+ , Exception const& x, Context const& context)
+ {
+ std::string which = x.which();
+ auto iter = id_map.find(which);
+ if (iter != id_map.end())
+ which = iter->second;
+
+ std::string message = "Error! Expecting: " + which + " here:";
+ auto& error_handler = x3::get<error_handler_tag>(context).get();
+ error_handler(x.where(), message);
+ return x3::error_handler_result::fail;
+ }
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/printer.hpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/printer.hpp
new file mode 100644
index 00000000..a1c307c6
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/printer.hpp
@@ -0,0 +1,57 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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_X3_REPR_PRINTER_HPP)
+#define BOOST_SPIRIT_X3_REPR_PRINTER_HPP
+
+#include "ast.hpp"
+
+#include <ostream>
+
+namespace rexpr { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Print out the rexpr tree
+ ///////////////////////////////////////////////////////////////////////////
+ int const tabsize = 4;
+
+ struct rexpr_printer
+ {
+ typedef void result_type;
+
+ rexpr_printer(std::ostream& out, int indent = 0)
+ : out(out), indent(indent) {}
+
+ void operator()(rexpr const& ast) const
+ {
+ out << '{' << std::endl;
+ for (auto const& entry : ast.entries)
+ {
+ tab(indent+tabsize);
+ out << '"' << entry.first << "\" = ";
+ boost::apply_visitor(rexpr_printer(out, indent+tabsize), entry.second);
+ }
+ tab(indent);
+ out << '}' << std::endl;
+ }
+
+ void operator()(std::string const& text) const
+ {
+ out << '"' << text << '"' << std::endl;
+ }
+
+ void tab(int spaces) const
+ {
+ for (int i = 0; i < spaces; ++i)
+ out << ' ';
+ }
+
+ std::ostream& out;
+ int indent;
+ };
+}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/rexpr.hpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/rexpr.hpp
new file mode 100644
index 00000000..f3979f9d
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/rexpr.hpp
@@ -0,0 +1,33 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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_X3_REXPR_HPP)
+#define BOOST_SPIRIT_X3_REXPR_HPP
+
+#include "ast.hpp"
+
+#include <boost/spirit/home/x3.hpp>
+
+namespace rexpr
+{
+ namespace x3 = boost::spirit::x3;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // rexpr public interface
+ ///////////////////////////////////////////////////////////////////////////
+ namespace parser
+ {
+ struct rexpr_class;
+ typedef
+ x3::rule<rexpr_class, ast::rexpr>
+ rexpr_type;
+ BOOST_SPIRIT_DECLARE(rexpr_type);
+ }
+
+ parser::rexpr_type const& rexpr();
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/rexpr_def.hpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/rexpr_def.hpp
new file mode 100644
index 00000000..3875031a
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/rexpr/rexpr_def.hpp
@@ -0,0 +1,94 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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_X3_REPR_REXPR_DEF_HPP)
+#define BOOST_SPIRIT_X3_REPR_REXPR_DEF_HPP
+
+#include "ast.hpp"
+#include "ast_adapted.hpp"
+#include "error_handler.hpp"
+#include "rexpr.hpp"
+
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/utility/annotate_on_success.hpp>
+
+namespace rexpr { namespace parser
+{
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ using x3::lit;
+ using x3::lexeme;
+
+ using ascii::char_;
+ using ascii::string;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Rule IDs
+ ///////////////////////////////////////////////////////////////////////////
+
+ struct rexpr_value_class;
+ struct rexpr_key_value_class;
+ struct rexpr_inner_class;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Rules
+ ///////////////////////////////////////////////////////////////////////////
+
+ x3::rule<rexpr_value_class, ast::rexpr_value> const
+ rexpr_value = "rexpr_value";
+
+ x3::rule<rexpr_key_value_class, ast::rexpr_key_value> const
+ rexpr_key_value = "rexpr_key_value";
+
+ x3::rule<rexpr_inner_class, ast::rexpr> const
+ rexpr_inner = "rexpr";
+
+ rexpr_type const rexpr = "rexpr";
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Grammar
+ ///////////////////////////////////////////////////////////////////////////
+
+ auto const quoted_string =
+ lexeme['"' >> *(char_ - '"') >> '"'];
+
+ auto const rexpr_value_def =
+ quoted_string | rexpr_inner;
+
+ auto const rexpr_key_value_def =
+ quoted_string > '=' > rexpr_value;
+
+ auto const rexpr_inner_def =
+ '{' > *rexpr_key_value > '}';
+
+ auto const rexpr_def = rexpr_inner_def;
+
+ BOOST_SPIRIT_DEFINE(rexpr_value, rexpr, rexpr_inner, rexpr_key_value);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Annotation and Error handling
+ ///////////////////////////////////////////////////////////////////////////
+
+ // We want these to be annotated with the iterator position.
+ struct rexpr_value_class : x3::annotate_on_success {};
+ struct rexpr_key_value_class : x3::annotate_on_success {};
+ struct rexpr_inner_class : x3::annotate_on_success {};
+
+ // We want error-handling only for the start (outermost) rexpr
+ // rexpr is the same as rexpr_inner but without error-handling (see error_handler.hpp)
+ struct rexpr_class : x3::annotate_on_success, error_handler_base {};
+}}
+
+namespace rexpr
+{
+ parser::rexpr_type const& rexpr()
+ {
+ return parser::rexpr;
+ }
+}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/src/rexpr.cpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/src/rexpr.cpp
new file mode 100644
index 00000000..14b84c60
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/src/rexpr.cpp
@@ -0,0 +1,14 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "../rexpr/rexpr_def.hpp"
+#include "../rexpr/config.hpp"
+
+namespace rexpr { namespace parser
+{
+ BOOST_SPIRIT_INSTANTIATE(
+ rexpr_type, iterator_type, context_type);
+}}
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/Jamfile b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/Jamfile
new file mode 100644
index 00000000..4952e281
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/Jamfile
@@ -0,0 +1,23 @@
+#
+# Copyright (C) 2015 Michael Caisse, ciere.com
+#
+# Distributed under the Boost Software License, Version 1.0. (See accompanying
+# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#
+
+import testing ;
+
+project
+ : requirements
+ <source>..//rexpr
+ <source>/boost//regex
+ <source>/boost//filesystem
+ <c++-template-depth>300
+ ;
+
+path-constant TEST_FILES : test_files ;
+
+unit-test parse_rexpr_test
+ : parse_rexpr_test.cpp
+ : <testing.arg>"$(TEST_FILES)"
+ ;
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/parse_rexpr_test.cpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/parse_rexpr_test.cpp
new file mode 100644
index 00000000..bdbacf2d
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/parse_rexpr_test.cpp
@@ -0,0 +1,86 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the Boost 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 <iterator>
+#include <algorithm>
+#include <sstream>
+
+#include "../rexpr/ast.hpp"
+#include "../rexpr/rexpr.hpp"
+#include "../rexpr/error_handler.hpp"
+#include "../rexpr/config.hpp"
+#include "../rexpr/printer.hpp"
+
+#include "testing.hpp"
+
+namespace fs = boost::filesystem;
+namespace testing = boost::spirit::x3::testing;
+
+auto parse = [](std::string const& source, fs::path input_path)-> std::string
+{
+ std::stringstream out;
+
+ using rexpr::parser::iterator_type;
+ iterator_type iter(source.begin());
+ iterator_type const end(source.end());
+
+ // Our AST
+ rexpr::ast::rexpr ast;
+
+ // Our error handler
+ using boost::spirit::x3::with;
+ using rexpr::parser::error_handler_type;
+ using rexpr::parser::error_handler_tag;
+ error_handler_type error_handler(iter, end, out, input_path.string()); // Our error handler
+
+ // Our parser
+ auto const parser =
+ // we pass our error handler to the parser so we can access
+ // it later on in our on_error and on_sucess handlers
+ with<error_handler_tag>(std::ref(error_handler))
+ [
+ rexpr::rexpr()
+ ];
+
+ // Go forth and parse!
+ using boost::spirit::x3::ascii::space;
+ bool success = phrase_parse(iter, end, parser, space, ast);
+
+ if (success)
+ {
+ if (iter != end)
+ error_handler(iter, "Error! Expecting end of input here: ");
+ else
+ rexpr::ast::rexpr_printer{out}(ast);
+ }
+
+ return out.str();
+};
+
+int num_files_tested = 0;
+auto compare = [](fs::path input_path, fs::path expect_path)
+{
+ testing::compare(input_path, expect_path, parse);
+ ++num_files_tested;
+};
+
+int main(int argc, char* argv[])
+{
+ if (argc < 2)
+ {
+ std::cout << "usage: " << fs::path(argv[0]).filename() << " path/to/test/files" << std::endl;
+ return -1;
+ }
+
+ std::cout << "===================================================================================================" << std::endl;
+ std::cout << "Testing: " << fs::absolute(fs::path(argv[1])) << std::endl;
+ int r = testing::for_each_file(fs::path(argv[1]), compare);
+ if (r == 0)
+ std::cout << num_files_tested << " files tested." << std::endl;
+ std::cout << "===================================================================================================" << std::endl;
+ return r;
+}
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/a.expect b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/a.expect
new file mode 100644
index 00000000..635c145b
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/a.expect
@@ -0,0 +1,8 @@
+{
+ "color" = "blue"
+ "position" = {
+ "x" = "123"
+ "y" = "456"
+ }
+ "size" = "29 cm."
+}
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/a.input b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/a.input
new file mode 100644
index 00000000..880f5bac
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/a.input
@@ -0,0 +1,8 @@
+{
+ "color" = "blue"
+ "size" = "29 cm."
+ "position" = {
+ "x" = "123"
+ "y" = "456"
+ }
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/b.expect b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/b.expect
new file mode 100644
index 00000000..3f485184
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/b.expect
@@ -0,0 +1,4 @@
+In file <%.*?b.input%>, line 4:
+Error! Expecting: Value here:
+ "position" = $
+_________________^_ \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/b.input b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/b.input
new file mode 100644
index 00000000..6f0743b1
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/b.input
@@ -0,0 +1,8 @@
+{
+ "color" = "blue"
+ "size" = "29 cm."
+ "position" = $
+ "x" = "123"
+ "y" = "456"
+ }
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/c.expect b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/c.expect
new file mode 100644
index 00000000..bc7efcd0
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/c.expect
@@ -0,0 +1,4 @@
+In file <%.*?c.input%>, line 5:
+Error! Expecting: '}' here:
+ banana
+________^_ \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/c.input b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/c.input
new file mode 100644
index 00000000..6eaa1259
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/c.input
@@ -0,0 +1,8 @@
+{
+ "color" = "blue"
+ "size" = "29 cm."
+ "position" = {
+ banana
+ "y" = "456"
+ }
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/d.expect b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/d.expect
new file mode 100644
index 00000000..5b376035
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/d.expect
@@ -0,0 +1,4 @@
+In file <%.*?d.input%>, line 5:
+Error! Expecting: '=' here:
+ "x" : "123"
+____________^_
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/d.input b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/d.input
new file mode 100644
index 00000000..c8be6438
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/d.input
@@ -0,0 +1,8 @@
+{
+ "color" = "blue"
+ "size" = "29 cm."
+ "position" = {
+ "x" : "123"
+ "y" = "456"
+ }
+} \ No newline at end of file
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/e.expect b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/e.expect
new file mode 100644
index 00000000..4fed2140
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/e.expect
@@ -0,0 +1,5 @@
+In file <%.*?e.input%>, line 8:
+Error! Expecting end of input here:
+};
+_^_
+
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/e.input b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/e.input
new file mode 100644
index 00000000..1bd447f1
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/test_files/e.input
@@ -0,0 +1,8 @@
+{
+ "color" = "blue"
+ "size" = "29 cm."
+ "position" = {
+ "x" = "123"
+ "y" = "456"
+ }
+};
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/testing.hpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/testing.hpp
new file mode 100644
index 00000000..eb99f692
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_full/test/testing.hpp
@@ -0,0 +1,269 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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_X3_TEST_UTILITIES)
+#define BOOST_SPIRIT_X3_TEST_UTILITIES
+
+#include <boost/regex.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
+
+namespace boost { namespace spirit { namespace x3 { namespace testing
+{
+ namespace fs = boost::filesystem;
+
+ ////////////////////////////////////////////////////////////////////////////
+ // compare
+ //
+ // Compares the contents of in with the template tem. The template
+ // may include embedded regular expressions marked up within re_prefix
+ // and re_suffix tags. For example, given the default RE markup, this
+ // template <%[0-9]+%> will match any integer in in. The function
+ // will return the first non-matching position. The flag full_match
+ // indicates a full match. It is possible for returned pos to be
+ // at the end of in (in.end()) while still returning full_match ==
+ // false. In that case, we have a partial match.
+ ////////////////////////////////////////////////////////////////////////////
+
+ template <typename Iterator>
+ struct compare_result
+ {
+ compare_result(
+ Iterator pos
+ , bool full_match
+ ) : pos(pos), full_match(full_match) {}
+
+ Iterator pos;
+ bool full_match;
+ };
+
+ template <typename Range>
+ compare_result<typename Range::const_iterator>
+ compare(
+ Range const& in
+ , Range const& tem
+ , char const* re_prefix = "<%"
+ , char const* re_suffix = "%>"
+ );
+
+ ////////////////////////////////////////////////////////////////////////////
+ // compare
+ //
+ // 1) Call f, given the contents of input_path loaded in a string.
+ // The result of calling f is the output string.
+ // 2) Compare the result of calling f with expected template
+ // file (expect_path) using the low-level compare utility
+ // abive
+ ////////////////////////////////////////////////////////////////////////////
+ template <typename F>
+ bool compare(
+ fs::path input_path, fs::path expect_path
+ , F f
+ , char const* re_prefix = "<%"
+ , char const* re_suffix = "%>"
+ );
+
+ ////////////////////////////////////////////////////////////////////////////
+ // for_each_file
+ //
+ // For each *.input and *.expect file in a given directory,
+ // call the function f, passing in the *.input and *.expect paths.
+ ////////////////////////////////////////////////////////////////////////////
+ template <typename F>
+ int for_each_file(fs::path p, F f);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // load_file
+ //
+ // Load file into a string.
+ ////////////////////////////////////////////////////////////////////////////
+ std::string load(fs::path p);
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Implementation
+ ////////////////////////////////////////////////////////////////////////////
+
+ template <typename Iterator>
+ inline bool is_regex(
+ Iterator& first
+ , Iterator last
+ , std::string& re
+ , char const* re_prefix
+ , char const* re_suffix
+ )
+ {
+ boost::regex e(re_prefix + std::string("(.*?)") + re_suffix);
+ boost::match_results<Iterator> what;
+ if (boost::regex_search(
+ first, last, what, e
+ , boost::match_default | boost::match_continuous))
+ {
+ re = what[1].str();
+ first = what[0].second;
+ return true;
+ }
+ return false;
+ }
+
+ template <typename Range>
+ inline compare_result<typename Range::const_iterator>
+ compare(
+ Range const& in
+ , Range const& tem
+ , char const* re_prefix
+ , char const* re_suffix
+ )
+ {
+ typedef typename Range::const_iterator iter_t;
+ typedef compare_result<iter_t> compare_result_t;
+
+ iter_t in_first = in.begin();
+ iter_t in_last = in.end();
+ iter_t tem_first = tem.begin();
+ iter_t tem_last = tem.end();
+ std::string re;
+
+ while (in_first != in_last && tem_first != tem_last)
+ {
+ if (is_regex(tem_first, tem_last, re, re_prefix, re_suffix))
+ {
+ boost::match_results<iter_t> what;
+ boost::regex e(re);
+ if (!boost::regex_search(
+ in_first, in_last, what, e
+ , boost::match_default | boost::match_continuous))
+ {
+ // RE mismatch: exit now.
+ return compare_result_t(in_first, false);
+ }
+ else
+ {
+ // RE match: gobble the matching string.
+ in_first = what[0].second;
+ }
+ }
+ else
+ {
+ // Char by char comparison. Exit if we have a mismatch.
+ if (*in_first++ != *tem_first++)
+ return compare_result_t(in_first, false);
+ }
+ }
+
+ // Ignore trailing spaces in template
+ bool has_trailing_nonspaces = false;
+ while (tem_first != tem_last)
+ {
+ if (!std::isspace(*tem_first++))
+ {
+ has_trailing_nonspaces = true;
+ break;
+ }
+ }
+ while (in_first != in_last)
+ {
+ if (!std::isspace(*in_first++))
+ {
+ has_trailing_nonspaces = true;
+ break;
+ }
+ }
+ // return a full match only if the template is fully matched and if there
+ // are no more characters to match in the source
+ return compare_result_t(in_first, !has_trailing_nonspaces);
+ }
+
+ template <typename F>
+ inline int for_each_file(fs::path p, F f)
+ {
+ try
+ {
+ if (fs::exists(p) && fs::is_directory(p))
+ {
+ for (auto i = fs::directory_iterator(p); i != fs::directory_iterator(); ++i)
+ {
+ auto ext = fs::extension(i->path());
+ if (ext == ".input")
+ {
+ auto input_path = i->path();
+ auto expect_path = input_path;
+ expect_path.replace_extension(".expect");
+ f(input_path, expect_path);
+ }
+ }
+ }
+ else
+ {
+ std::cerr << "Directory: " << fs::absolute(p) << " does not exist." << std::endl;
+ return 1;
+ }
+ }
+
+ catch (const fs::filesystem_error& ex)
+ {
+ std::cerr << ex.what() << '\n';
+ return 1;
+ }
+ return 0;
+ }
+
+ inline std::string load(fs::path p)
+ {
+ boost::filesystem::ifstream file(p);
+ if (!file)
+ return "";
+ std::string contents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
+ return contents;
+ }
+
+ template <typename F>
+ inline bool compare(
+ fs::path input_path, fs::path expect_path
+ , F f
+ , char const* re_prefix
+ , char const* re_suffix
+ )
+ {
+ std::string output = f(load(input_path), input_path);
+ std::string expected = load(expect_path);
+
+ auto result = compare(output, expected, re_prefix, re_suffix);
+ if (!result.full_match)
+ {
+ std::cout << "=============================================" << std::endl;
+ std::cout << "==== Mismatch Found:" << std::endl;
+ int line = 1;
+ int col = 1;
+ for (auto i = output.begin(); i != result.pos; ++i)
+ {
+ if (*i == '\n')
+ {
+ line++;
+ col = 0;
+ }
+ ++col;
+ }
+
+ std::cerr
+ << "==== File: " << expect_path
+ << ", Line: " << line
+ << ", Column: " << col
+ << std::endl;
+ std::cerr << "=============================================" << std::endl;
+
+ // Print output
+ std::cerr << output;
+ std::cerr << "=============================================" << std::endl;
+ std::cerr << "==== End" << std::endl;
+ std::cerr << "=============================================" << std::endl;
+ return false;
+ }
+ return true;
+ }
+
+}}}}
+
+#endif
diff --git a/src/boost/libs/spirit/example/x3/rexpr/rexpr_min/rexpr.cpp b/src/boost/libs/spirit/example/x3/rexpr/rexpr_min/rexpr.cpp
new file mode 100644
index 00000000..f3a3556d
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/rexpr/rexpr_min/rexpr.cpp
@@ -0,0 +1,215 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+
+ Distributed under the 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 simple parser for X3 intended as a minimal starting point.
+// 'rexpr' is a parser for a language resembling a minimal subset
+// of json, but limited to a dictionary (composed of key=value pairs)
+// where the value can itself be a string or a recursive dictionary.
+//
+// Example:
+//
+// {
+// "color" = "blue"
+// "size" = "29 cm."
+// "position" = {
+// "x" = "123"
+// "y" = "456"
+// }
+// }
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <boost/spirit/home/x3/support/ast/variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/std_pair.hpp>
+#include <boost/fusion/include/io.hpp>
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <map>
+
+///////////////////////////////////////////////////////////////////////////////
+// Our AST
+///////////////////////////////////////////////////////////////////////////////
+namespace client { namespace ast
+{
+ namespace fusion = boost::fusion;
+ namespace x3 = boost::spirit::x3;
+
+ struct rexpr;
+
+ struct rexpr_value : x3::variant<
+ std::string
+ , x3::forward_ast<rexpr>
+ >
+ {
+ using base_type::base_type;
+ using base_type::operator=;
+ };
+
+ typedef std::map<std::string, rexpr_value> rexpr_map;
+ typedef std::pair<std::string, rexpr_value> rexpr_key_value;
+
+ struct rexpr
+ {
+ rexpr_map entries;
+ };
+}}
+
+// We need to tell fusion about our rexpr struct
+// to make it a first-class fusion citizen
+BOOST_FUSION_ADAPT_STRUCT(client::ast::rexpr,
+ entries
+)
+
+///////////////////////////////////////////////////////////////////////////////
+// AST processing
+///////////////////////////////////////////////////////////////////////////////
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // Print out the rexpr tree
+ ///////////////////////////////////////////////////////////////////////////
+ int const tabsize = 4;
+
+ struct rexpr_printer
+ {
+ typedef void result_type;
+
+ rexpr_printer(int indent = 0)
+ : indent(indent) {}
+
+ void operator()(rexpr const& ast) const
+ {
+ std::cout << '{' << std::endl;
+ for (auto const& entry : ast.entries)
+ {
+ tab(indent+tabsize);
+ std::cout << '"' << entry.first << "\" = ";
+ boost::apply_visitor(rexpr_printer(indent+tabsize), entry.second);
+ }
+ tab(indent);
+ std::cout << '}' << std::endl;
+ }
+
+ void operator()(std::string const& text) const
+ {
+ std::cout << '"' << text << '"' << std::endl;
+ }
+
+ void tab(int spaces) const
+ {
+ for (int i = 0; i < spaces; ++i)
+ std::cout << ' ';
+ }
+
+ int indent;
+ };
+}}
+
+///////////////////////////////////////////////////////////////////////////////
+// Our rexpr grammar
+///////////////////////////////////////////////////////////////////////////////
+namespace client { namespace parser
+{
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ using x3::lit;
+ using x3::lexeme;
+
+ using ascii::char_;
+ using ascii::string;
+
+ x3::rule<class rexpr_value, ast::rexpr_value>
+ rexpr_value = "rexpr_value";
+
+ x3::rule<class rexpr, ast::rexpr>
+ rexpr = "rexpr";
+
+ x3::rule<class rexpr_key_value, ast::rexpr_key_value>
+ rexpr_key_value = "rexpr_key_value";
+
+ auto const quoted_string =
+ lexeme['"' >> *(char_ - '"') >> '"'];
+
+ auto const rexpr_value_def =
+ quoted_string | rexpr;
+
+ auto const rexpr_key_value_def =
+ quoted_string >> '=' >> rexpr_value;
+
+ auto const rexpr_def =
+ '{' >> *rexpr_key_value >> '}';
+
+ BOOST_SPIRIT_DEFINE(rexpr_value, rexpr, rexpr_key_value);
+}}
+
+///////////////////////////////////////////////////////////////////////////////
+// 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));
+
+ using client::parser::rexpr; // Our grammar
+ client::ast::rexpr ast; // Our tree
+
+ using boost::spirit::x3::ascii::space;
+ std::string::const_iterator iter = storage.begin();
+ std::string::const_iterator end = storage.end();
+ bool r = phrase_parse(iter, end, rexpr, space, ast);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "-------------------------\n";
+ client::ast::rexpr_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;
+ }
+}
diff --git a/src/boost/libs/spirit/example/x3/roman.cpp b/src/boost/libs/spirit/example/x3/roman.cpp
new file mode 100644
index 00000000..7423c19c
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/roman.cpp
@@ -0,0 +1,179 @@
+/*=============================================================================
+ Copyright (c) 2001-2015 Joel de Guzman
+ Copyright (c) 2015 Ahmed Charles
+
+ Distributed under the 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
+// [ JDG May 13, 2015 ] spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // Parse roman hundreds (100..900) numerals using the symbol table.
+ // Notice that the data associated with each slot is the parser's attribute
+ // (which is passed to attached semantic actions).
+ ///////////////////////////////////////////////////////////////////////////////
+ struct hundreds_ : x3::symbols<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_ : x3::symbols<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_ : x3::symbols<unsigned>
+ {
+ ones_()
+ {
+ add
+ ("I" , 1)
+ ("II" , 2)
+ ("III" , 3)
+ ("IV" , 4)
+ ("V" , 5)
+ ("VI" , 6)
+ ("VII" , 7)
+ ("VIII" , 8)
+ ("IX" , 9)
+ ;
+ }
+
+ } ones;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // roman (numerals) grammar
+ //
+ // Note the use of the || operator. The expression
+ // a || b reads match a or b and in sequence. Try
+ // defining the roman numerals grammar in YACC or
+ // PCCTS. Spirit rules! :-)
+ ///////////////////////////////////////////////////////////////////////////////
+ namespace parser
+ {
+ using x3::eps;
+ using x3::lit;
+ using x3::_val;
+ using x3::_attr;
+ using ascii::char_;
+
+ auto set_zero = [](auto& ctx){ _val(ctx) = 0; };
+ auto add1000 = [](auto& ctx){ _val(ctx) += 1000; };
+ auto add = [](auto& ctx){ _val(ctx) += _attr(ctx); };
+
+ x3::rule<class roman, unsigned> const roman = "roman";
+
+ auto const roman_def =
+ eps [set_zero]
+ >>
+ (
+ -(+lit('M') [add1000])
+ >> -hundreds [add]
+ >> -tens [add]
+ >> -ones [add]
+ )
+ ;
+
+ BOOST_SPIRIT_DEFINE(roman);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// 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;
+ using client::parser::roman; // Our parser
+
+ std::string str;
+ unsigned result;
+ while (std::getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ iterator_type iter = str.begin();
+ iterator_type const end = str.end();
+ bool r = parse(iter, end, roman, result);
+
+ if (r && iter == end)
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << "result = " << result << std::endl;
+ std::cout << "-------------------------\n";
+ }
+ else
+ {
+ std::string rest(iter, end);
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "stopped at: \": " << rest << "\"\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}
diff --git a/src/boost/libs/spirit/example/x3/sum.cpp b/src/boost/libs/spirit/example/x3/sum.cpp
new file mode 100644
index 00000000..81315fb2
--- /dev/null
+++ b/src/boost/libs/spirit/example/x3/sum.cpp
@@ -0,0 +1,98 @@
+/*=============================================================================
+ Copyright (c) 2002-2015 Joel de Guzman
+
+ Distributed under the 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
+// [ JDG May 12, 2015 ] spirit X3
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/spirit/home/x3.hpp>
+#include <iostream>
+#include <string>
+
+namespace client
+{
+ namespace x3 = boost::spirit::x3;
+ namespace ascii = boost::spirit::x3::ascii;
+
+ using x3::double_;
+ using ascii::space;
+ using x3::_attr;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Our adder
+ ///////////////////////////////////////////////////////////////////////////
+
+ template <typename Iterator>
+ bool adder(Iterator first, Iterator last, double& n)
+ {
+ auto assign = [&](auto& ctx){ n = _attr(ctx); };
+ auto add = [&](auto& ctx){ n += _attr(ctx); };
+
+ bool r = x3::phrase_parse(first, last,
+
+ // Begin grammar
+ (
+ double_[assign] >> *(',' >> double_[add])
+ )
+ ,
+ // End grammar
+
+ space);
+
+ if (first != last) // fail if we did not get a full match
+ return false;
+ return r;
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////
+// Main program
+////////////////////////////////////////////////////////////////////////////
+int
+main()
+{
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+ std::cout << "\t\tA parser for summing a list of numbers...\n\n";
+ std::cout << "/////////////////////////////////////////////////////////\n\n";
+
+ std::cout << "Give me a comma separated list of numbers.\n";
+ std::cout << "The numbers are added using Phoenix.\n";
+ std::cout << "Type [q or Q] to quit\n\n";
+
+ std::string str;
+ while (getline(std::cin, str))
+ {
+ if (str.empty() || str[0] == 'q' || str[0] == 'Q')
+ break;
+
+ double n;
+ if (client::adder(str.begin(), str.end(), n))
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing succeeded\n";
+ std::cout << str << " Parses OK: " << std::endl;
+
+ std::cout << "sum = " << n;
+ std::cout << "\n-------------------------\n";
+ }
+ else
+ {
+ std::cout << "-------------------------\n";
+ std::cout << "Parsing failed\n";
+ std::cout << "-------------------------\n";
+ }
+ }
+
+ std::cout << "Bye... :-) \n\n";
+ return 0;
+}