### Setup Namespaces and Using Directives for Spirit X3 Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/x3/html/spirit_x3/tutorials/sum___adding_numbers Establishes namespace aliases and using declarations for Boost Spirit X3 components. This simplifies syntax by reducing the need for fully-qualified names throughout the parser code. ```cpp namespace x3 = boost::spirit::x3; namespace ascii = boost::spirit::x3::ascii; using x3::double_; using ascii::space; using x3::_attr; ``` -------------------------------- ### Include Headers for Boost.Lex, Boost.Qi, and Boost.Phoenix Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/lex/tutorials/lexer_quickstart3 Includes essential header files for using Boost.Lex for lexical analysis, Boost.Qi for parsing, and Boost.Phoenix for functional programming constructs. These are required for the word counting example. ```cpp #include #include #include #include #include ``` -------------------------------- ### Flex Reference Implementation for Word Counter Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/lex/tutorials/lexer_quickstart2 Original Flex lexer program that serves as the reference implementation for the Spirit.Lex example. Demonstrates basic pattern matching and action execution for counting lines, words, and characters from input text. ```lex %{ 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); } ``` -------------------------------- ### Setup Boost Spirit Namespaces Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/qi/distinct Configures the necessary using declarations for Boost Spirit, ASCII character classes, and the distinct parser. This simplifies the code by making the parser components directly accessible without full namespace qualification. ```cpp using namespace boost::spirit; using namespace boost::spirit::ascii; using boost::spirit::repository::distinct; ``` -------------------------------- ### Grammar Rule Formatting Example (Spirit/C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/doc/style_guide Demonstrates the recommended formatting for a grammar rule in Spirit, including indentation and breaking operands onto separate lines for clarity. This style aims for an aesthetically pleasing and easy-to-read grammar. ```spirit program = program_heading [heading_action] >> block [block_action] >> '.' | another_sequence >> etc ; ``` -------------------------------- ### Boost.Spirit.Qi advance Parser Grammar Setup (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/doc/html/spirit_repository/qi_components/primitive/advance A C++ grammar example using Spirit.Qi's 'advance' component. This grammar parses binary data, using 'advance' to efficiently skip fields whose lengths are specified by preceding bytes. It also shows handling alternatives. ```cpp template struct advance_grammar : qi::grammar > { advance_grammar() : advance_grammar::base_type(start) { using qi::byte_; using qi::eoi; using namespace qi::labels; start = byte_ [_a = _1] >> advance(_a) >> "boost" >> byte_ [_a = _1] >> (advance(_a) | "qi") // note alternative when advance fails >> eoi ; } qi::rule > start; }; ``` -------------------------------- ### Boost.Spirit.Karma attr_cast Example Setup Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/karma/reference/auxiliary/attr_cast Sets up the necessary includes and using declarations for the Boost.Spirit.Karma `attr_cast` example. It includes Karma, support for utree, Phoenix core and operator, Fusion, Proto, and standard I/O utilities. ```cpp #include #include #include #include #include #include #include #include using boost::spirit::karma::int_; ``` -------------------------------- ### Main Function for Word Count Example Source: https://www.boost.org/doc/libs/latest/libs/spirit/example/lex/word_count The main function sets up the lexer and grammar, reads input from a file, tokenizes the input, and parses it using the defined grammar. It then prints the resulting counts. ```C++ //[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 > token_type; /*< Define the lexer type to use implementing the state machine >*/ typedef lex::lexertl::lexer lexer_type; /*< Define the iterator type exposed by the lexer type >*/ typedef word_count_tokens::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 word_count; // Our lexer word_count_grammar 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 ``` -------------------------------- ### C++ Boost.Spirit Calculator Main Program Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/qi/calc1_sr The main function to run the Boost.Spirit calculator example. It initializes the grammar, takes user input for expressions, parses them using the defined grammar, and reports success or failure. It allows users to quit by entering 'q' or 'Q'. ```cpp /////////////////////////////////////////////////////////////////////////////// // 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; typedef std::string::const_iterator iterator_type; typedef client::calculator 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(); 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; } ``` -------------------------------- ### Boost.Spirit: Define XML grammar with auto-rules Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/tutorials/mini_xml___asts_ A Boost.Spirit grammar for parsing XML using auto-rules, making the grammar semantic-action-less. It defines rules for text, nodes, start tags, and end tags, employing `qi::locals` for string storage and `_a` for attribute assignment. ```cpp template struct mini_xml_grammar : qi::grammar, 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, ascii::space_type> xml; qi::rule node; qi::rule text; qi::rule start_tag; qi::rule end_tag; }; ``` -------------------------------- ### Full Boost Grammar Example: Calculator Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/doc/grammar Presents a complete example of a calculator grammar implemented using Boost.Spirit. It defines rules for 'expression', 'term', 'factor', and 'group' within the nested 'definition' struct, demonstrating complex rule composition. ```cpp struct calculator : public grammar { template struct definition { definition(calculator const& self) { group = '(' >> expression >> ')'; factor = integer | group; term = factor >> *(('*' >> factor) | ('/' >> factor)); expression = term >> *(('+' >> term) | ('-' >> term)); } rule expression, term, factor, group; rule const& start() const { return expression; } }; }; ``` -------------------------------- ### Boost.Spirit Qi Sequence Parser Usage Examples (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/reference/operator/sequence Demonstrates various ways to use the Boost.Spirit Qi sequence parser. Examples include simple parsing, attribute extraction using Boost.Fusion and STL, and attribute extraction with semantic actions. ```cpp using boost::spirit::ascii::char_; using boost::spirit::qi::_1; using boost::spirit::qi::_2; namespace bf = boost::fusion; // Simple usage: test_parser("xy", char_ >> char_); // Extracting the attribute tuple (using Boost.Fusion): bf::vector 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 vec; test_parser_attr("xy", char_ >> char_, vec); std::cout << vec[0] << ',' << vec[1] << std::endl; // Extracting the attributes using Semantic Actions (using Boost.Phoenix): test_parser("xy", (char_ >> char_)[std::cout << _1 << ',' << _2 << std::endl]); ``` -------------------------------- ### Instantiate and Execute Lexer in C++ Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/lex/tutorials/lexer_quickstart2 Demonstrates how to instantiate a lexer, feed it input from a file, and iterate over the generated tokens to perform lexical analysis. It includes type definitions for tokens and lexers, input reading, iterator creation, and outputting results or error messages. Optimizations like omitting token attributes and lexer state are also shown. ```C++ int main(int argc, char* argv[]) { typedef lex::lexertl::token token_type; typedef lex::lexertl::actor_lexer lexer_type; word_count_tokens word_count_lexer; 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()]; lexer_type::iterator_type iter = word_count_lexer.begin(first, last); lexer_type::iterator_type end = word_count_lexer.end(); 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; } ``` -------------------------------- ### Boost.Spirit Start Tag Rule (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/tutorials/mini_xml___asts_ Defines the 'start_tag' rule for parsing XML start tags. It includes a 'Not Predicate' to ensure it doesn't match an end tag and uses a lexeme to capture the tag name. ```cpp qi::rule start_tag; start_tag = '<' >> !char_('/') >> lexeme[+(char_ - '>') [_val += _1]] >> '>' ; ``` -------------------------------- ### Define Rule with Start Tag, Nodes, and End Tag (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/tutorials/mini_xml___asts_ This code defines the structure of the 'xml' rule, specifying how to parse a start tag, zero or more nodes, and an end tag. It shows how the parsed start-tag string is assigned to the local variable '_a' using a Phoenix placeholder and how this local variable is used with the end tag. ```C++ xml %= start_tag[_a = _1] >> *node >> end_tag(_a) ; ``` -------------------------------- ### Parse C++ Comments using Boost Spirit Qi confix Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/qi/confix Parses a C++ style comment, which starts with '//' and ends with a newline character. It uses the `confix` directive from Boost Spirit repository to define the start and end delimiters. The function takes iterators to the string and an attribute to store the comment content. It returns true if the parsing is successful and the entire input is consumed. ```C++ // Copyright (c) 2009 Chris Hoeppler // // Distributed under the 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 different use cases for the // confix directive. #include #include #include //[qi_confix_includes #include #include //] namespace client { //[qi_confix_using using boost::spirit::eol; using boost::spirit::lexeme; using boost::spirit::ascii::alnum; using boost::spirit::ascii::char_; using boost::spirit::ascii::space; using boost::spirit::qi::parse; using boost::spirit::qi::phrase_parse; using boost::spirit::repository::confix; //] //[qi_confix_cpp_comment template bool parse_cpp_comment(Iterator first, Iterator last, std::string& attr) { bool r = parse(first, last, confix("//", eol)[*(char_ - eol)], // grammar attr); // attribute if (!r || first != last) // fail if we did not get a full match return false; return r; } //] //[qi_confix_c_comment template bool parse_c_comment(Iterator first, Iterator last, std::string& attr) { bool r = parse(first, last, confix("/*", "*/")[*(char_ - "*/")], // grammar attr); // attribute if (!r || first != last) // fail if we did not get a full match return false; return r; } //] //[qi_confix_tagged_data template bool parse_tagged(Iterator first, Iterator last, std::string& attr) { bool r = phrase_parse(first, last, confix("", "")[lexeme[*(char_ - '<')]], // grammar space, // skip attr); // attribute if (!r || first != last) // fail if we did not get a full match return false; return r; } //] } int main() { // C++ comment std::string comment("// This is a comment\n"); std::string attr; bool r = client::parse_cpp_comment(comment.begin(), comment.end(), attr); std::cout << "Parsing a C++ comment"; if (r && attr == " This is a comment") std::cout << " succeeded." << std::endl; else std::cout << " failed" << std::endl; // C comment comment = "/* This is another comment */"; attr.clear(); r = client::parse_c_comment(comment.begin(), comment.end(), attr); std::cout << "Parsing a C comment"; if (r && attr == " This is another comment ") std::cout << " succeeded." << std::endl; else std::cout << " failed" << std::endl; // Tagged data std::string data = " This is the body. "; attr.clear(); r = client::parse_tagged(data.begin(), data.end(), attr); std::cout << "Parsing tagged data"; if (r && attr == "This is the body. ") std::cout << " succeeded." << std::endl; else std::cout << " failed" << std::endl; return 0; } ``` -------------------------------- ### Include Boost.Lex and Utility Headers Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/lex/tutorials/lexer_quickstart1 Includes the core Boost.Lex header for standalone lexical analysis and additional Boost headers for utility functions like boost::bind and boost::ref. These are essential for integrating Spirit.Lex into C++ projects. ```cpp #include #include #include ``` -------------------------------- ### Include Spirit.Lex and Boost.Phoenix Headers Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/lex/tutorials/lexer_quickstart2 Required header files for Spirit.Lex lexical analysis and Boost.Phoenix functors. These headers enable semantic actions and callable objects for token processing without additional external dependencies. ```cpp #include #include #include #include #include ``` -------------------------------- ### Boost Spirit Qi Confix Directive: Core Components Header Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/confix This C++ code snippet includes the main header for Boost.Spirit.Qi components along with the header for the confix directive. This setup is required for examples using the directive. ```cpp #include #include ``` -------------------------------- ### Include Headers for Boost Spirit X3 Parser Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/x3/html/spirit_x3/tutorials/sum___adding_numbers Required headers for using Boost Spirit X3 parsing library. Includes the main Spirit X3 header, standard I/O, and string utilities needed for the parser implementation. ```cpp #include #include #include ``` -------------------------------- ### Setup Namespace Aliases for Qi Seek Parser Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/doc/html/spirit_repository/qi_components/directives/seek Establishes namespace aliases for Boost Spirit Qi and Repository components to simplify code usage. These aliases are commonly used in examples and applications working with the seek directive. ```cpp namespace qi = boost::spirit::qi; namespace repo = boost::spirit::repository; ``` -------------------------------- ### Boost.Spirit Qi Advance Parser Includes Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/qi/advance Includes necessary headers for Boost.Spirit Qi, Phoenix operators, and the 'advance' parser from the Spirit repository. These are essential for defining and using the advance parser functionality. ```c++ #include #include #include ``` -------------------------------- ### Define Namespaces for Boost.Spirit Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/lex/tutorials/lexer_quickstart3 Establishes commonly used namespaces for Boost.Spirit and Boost.Spirit.ASCII to simplify syntax and improve code readability in Spirit-based grammars and lexer definitions. ```cpp using namespace boost::spirit; using namespace boost::spirit::ascii; ``` -------------------------------- ### Boost.Spirit Not Predicate Explanation (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/tutorials/mini_xml___asts_ Illustrates the 'Not Predicate' (`!p`) in Boost.Spirit, which attempts to match parser `p` but fails if `p` succeeds, without consuming input. It's used here to prevent parsing of end tags within start tags. ```cpp !p It will try the parser, `p`. If it is successful, fail; otherwise, pass. In other words, it negates the result of `p`. Like the `eps`, it does not consume any input though. It will always rewind the iterator position to where it was upon entry. So, the expression: !char_('/') basically says: we should not have a '/' at this point. ``` -------------------------------- ### Main Program for Calculator and AST Dumping Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/karma/calc2_ast_dump_sr The main function orchestrates the calculator example. It initializes the parser and generator grammars, reads user input expressions, parses them into an AST using the calculator grammar, and then generates a string representation of the AST using the dump_ast grammar. ```cpp /////////////////////////////////////////////////////////////////////////////// // 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 calculator; calculator calc; // Our generator grammar definitions typedef std::back_insert_iterator output_iterator_type; typedef dump_ast 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); ``` -------------------------------- ### Get Iterator to Line Start (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/support/line_pos_iterator The `get_line_start` C++ template function returns an iterator pointing to the beginning of the current line. This function is applicable to any type of iterator and takes the lower bound of the sequence and the current iterator position as input. ```cpp template inline Iterator get_line_start(Iterator lower_bound, Iterator current); ``` -------------------------------- ### Getting the Character Type of a String with char_type_of Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/reference/basics The `boost::spirit::traits::char_type_of` metafunction returns the underlying character type of a string type `S`. For example, for `std::string`, it would return `char`. This is useful for generic programming when dealing with strings. ```cpp template struct char_type_of : /* implementation detail */ {}; ``` -------------------------------- ### Main Program for Interactive Parsing Source: https://www.boost.org/doc/libs/latest/libs/spirit/example/x3/employee The main function provides an interactive command-line interface to test the employee parser. It prompts the user to enter employee data in the specified format, parses the input using the Spirit X3 employee parser, and reports whether the parsing was successful or not. It handles user input, error reporting, and graceful exit. ```cpp #include #include #include #include #include "employee_parser.hpp" int main() { std::cout << "/////////////////////////////////////////////////////////\\n\n"; std::cout << "\t\tAn employee parser for Spirit...\\n\n"; std::cout << "/////////////////////////////////////////////////////////"; 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; } ``` -------------------------------- ### C++ Main Function for Boost.Lex Word Count Example Source: https://www.boost.org/doc/libs/latest/libs/spirit/example/lex/word_count_lexer The main function sets up the lexer, reads input from a file (or defaults to 'word_count.input'), tokenizes the input using the defined word_count_tokens, and prints the calculated lines, words, and characters. It handles potential lexical analysis failures. ```cpp //[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 token_type; /*< This defines the lexer type to use >*/ typedef lex::lexertl::actor_lexer lexer_type; /*< Create the lexer object instance needed to invoke the lexical analysis >*/ word_count_tokens 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: \"" } return 0; } //] ``` -------------------------------- ### Boost.Spirit X3 Default (Throwing) Parser Example Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/x3/html/spirit_x3/tutorials/non_throwing_expectations This C++ code snippet demonstrates a typical Boost.Spirit X3 parser setup using the default behavior, which throws `expectation_failure` exceptions upon an error. It includes a `try-catch` block for handling these exceptions during parsing. ```cpp #include void do_parse() { // ... setup your variables here... try { bool const ok = x3::parse(first, last, parser); if (!ok) { // error handling } } catch (x3::expectation_failure const& failure) { // error handling } } ``` -------------------------------- ### Boost.Spirit Parser Rule Definition Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/tutorials/employee___parsing_into_structs Defines a 'start' rule in Boost.Spirit that parses an employee record. It includes literal strings, punctuation, integers, quoted strings, and doubles. The example shows the attribute type of the RHS before collapsing and the final compatible attribute type with the 'employee' struct. ```cpp start %= lit("employee") >> '{' >> int_ >> ',' >> quoted_string >> ',' >> quoted_string >> ',' >> double_ >> '}' ; ``` ```cpp fusion::vector ``` ```cpp struct employee { int age; std::string surname; std::string forename; double salary; }; ``` -------------------------------- ### Dynamically Create stored_rule with Alternative Operators in C++ Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/doc/stored_rule Example demonstrating how to dynamically build a stored_rule equivalent to the EBNF pattern 'start = *(a | b | c)' using step-by-step assignment and the copy() method. The copy() method is essential to avoid left-recursion when self-referencing a stored_rule. ```cpp stored_rule<> start; start = a; start = start.copy() | b; start = start.copy() | c; start = *(start.copy()); ``` -------------------------------- ### Boost.Spirit Grammar for Mini XML (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/tutorials/mini_xml___asts_ Defines a Boost.Spirit grammar to parse a minimalistic XML structure. It utilizes rules, lexemes, and semantic actions to build an in-memory representation. Dependencies include Boost.Spirit (qi, ascii) and Boost.Phoenix. ```cpp template struct mini_xml_grammar : qi::grammar { 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 xml; qi::rule node; qi::rule text; qi::rule start_tag; qi::rule end_tag; }; ``` -------------------------------- ### Boost.Spirit Select Parser Example Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/doc/select_parser This C++ snippet demonstrates the basic usage of the `select_p` parser from Boost.Spirit. It defines a rule that tries a list of parsers sequentially until one matches the input. The result indicates the position of the matching parser. ```cpp #include #include #include // Assuming parser_a, parser_b, ..., parser_n are defined elsewhere // rule<> parser_a, parser_b, ..., parser_n; boost::spirit::rule<> rule_select = boost::spirit::select_p ( parser_a , parser_b /* ... */ , parser_n ); ``` -------------------------------- ### Boost.Spirit Qi Grammar Definition and Usage Example (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/qi/reference/nonterminal/grammar Demonstrates how to define a basic grammar for parsing a list of numbers separated by commas using Boost.Spirit Qi. It includes necessary using declarations and shows how to instantiate and use the grammar with a test parser. ```c++ // forwards to #include // Example grammar definition struct num_list : boost::spirit::qi::grammar { num_list() : base_type(start) { using boost::spirit::int_; num = int_; start = num >> *(',' >> num); } boost::spirit::qi::rule start, num; }; // Example usage // num_list nlist; // test_phrase_parser("123, 456, 789", nlist); ``` -------------------------------- ### Access Alternative Grammar Rules with use_parser Template Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/doc/grammar Demonstrates how to parse using a specific grammar rule other than the default start rule. The use_parser template accepts a zero-based index corresponding to the order of rules passed to start_parsers(). This example uses the term rule (index 1) from the calculator2 grammar. ```cpp calculator2 g; if (parse( first, last, g.use_parser(), space_p ).full) { cout << "parsing succeeded\n"; } else { cout << "parsing failed\n"; } ``` -------------------------------- ### Sample Input Data for Boost Spirit Parsing (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/example/x3/error_handling Provides example input strings for the Boost.Spirit.X3 parser. Includes a 'good_input' string representing valid employee data and a 'bad_input' string with a syntax error to test the error handling capabilities. ```C++ 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 } )"; ``` -------------------------------- ### Tail Parser Solution for Backtracking in Spirit Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/rationale Shows the recommended solution pattern for handling greedy matching issues using a tail parser approach. The start parser is combined with an end parser (tail) to provide proper backtracking behavior. This technique is based on parsing theory from 'Parsing Techniques: A Practical Guide' section 6.6.2. ```spirit start >> end; ``` -------------------------------- ### Basic Boost.Karma Semantic Action Examples Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/karma/reference/action Demonstrates the usage of semantic actions with Boost.Karma generators for integer and string output. It shows how to assign values to the attribute using Phoenix references and values. ```cpp #include #include #include #include #include #include #include #include using boost::spirit::karma::int_; using boost::spirit::karma::string; using boost::spirit::karma::_1; using boost::phoenix::ref; using boost::phoenix::val; int i = 42; test_generator("42", int_[_1 = ref(i)]); test_generator("abc", string[_1 = val("abc")]); ``` -------------------------------- ### Boost.Spirit: while_p examples Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/doc/dynamic_parsers Provides examples of 'while_p' in Boost.Spirit. The first example shows parsing unsigned integers and accumulating their sum, handling multiple additions separated by '+'. The second example parses a string enclosed in double quotes, handling escaped characters within. ```C++ uint_p[assign_a(sum)] >> while_p('+')[uint_p[add(sum)]] "'" >> while_p(~eps_p("'"'))[c_escape_ch_p[push_back_a(result)]] >> "'" ``` -------------------------------- ### Boost Spirit X3 Headers and Namespace Setup Source: https://www.boost.org/doc/libs/latest/libs/spirit/example/x3/num_list/num_list2 Includes necessary Boost Spirit X3 headers and establishes namespace aliases for spirit parsing, ASCII character set operations, and standard C++ libraries. Sets up the foundation for using Spirit X3 parser combinators. ```C++ #include #include #include #include namespace client { namespace x3 = boost::spirit::x3; namespace ascii = boost::spirit::x3::ascii; } ``` -------------------------------- ### Parse C Comments using Boost Spirit Qi confix Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/qi/confix Parses a C style comment, which starts with '/*' and ends with '*/'. It utilizes the `confix` directive to specify these delimiters. The function accepts iterators to the input string and an attribute to capture the comment's content. It returns true upon successful parsing of the entire input. ```C++ template bool parse_c_comment(Iterator first, Iterator last, std::string& attr) { bool r = parse(first, last, confix("/*", "*/")[*(char_ - "*/")], // grammar attr); // attribute if (!r || first != last) // fail if we did not get a full match return false; return r; } ``` -------------------------------- ### Boost.Spirit: if_p example Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/doc/dynamic_parsers An example illustrating the use of 'if_p' in Boost.Spirit. This specific example uses 'if_p' to parse a hexadecimal number preceded by '0x', otherwise it parses an unsigned integer. ```C++ if_p("0x")[hex_p].else_p[uint_p] ``` -------------------------------- ### Spirit Karma Example Using Declarations (C++) Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/doc/html/spirit_repository/karma_components/nonterminal/subrule This C++ code snippet shows the common using declarations required for Spirit Karma, including namespaces for spirit, ascii, and the repository extension. ```cpp using namespace boost::spirit; using namespace boost::spirit::ascii; namespace repo = boost::spirit::repository; ``` -------------------------------- ### Nabialek Trick Grammar Implementation with Dynamic Rules Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/doc/techniques Demonstrates the optimized grammar using the Nabialek trick with a symbol table-based continuation dispatcher. The grammar dynamically selects between different production rules (one and two) based on matched keywords, then applies the selected rule to parse the remaining input. ```cpp one = name; two = name >> ',' >> name; continuations.add ("one", &one) ("two", &two) ; line = continuations[set_rest(rest)] >> rest; ``` -------------------------------- ### Define and Use Custom Skipper in C++ Source: https://www.boost.org/doc/libs/latest/libs/spirit/classic/example/techniques/typeof This C++ code snippet defines a custom skipper using the BOOST_TYPEOF macro, which is a technique from the Spirit documentation. The skipper is capable of parsing whitespace, C++ style single-line comments starting with '//', and multi-line comments enclosed in '/* */'. The code then uses this skipper to parse a sample string and asserts that the entire string was successfully parsed. ```C++ #include #include #include #include using namespace BOOST_SPIRIT_CLASSIC_NS; #define RULE(name, definition) BOOST_TYPEOF(definition) name = definition int main() { RULE( skipper, ( space_p | "//" >> *(anychar_p - '\n') >> '\n' | "/*" >> *(anychar_p - "*/") >> "*/" ) ); bool success = parse( "/*this is a comment*/\n//this is a c++ comment\n\n", *skipper).full; BOOST_ASSERT(success); std::cout << "SUCCESS!!!\n"; return 0; } ``` -------------------------------- ### Boost.Spirit Qi Advance Example 1: Parsing with std::string and std::list Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/qi/advance Demonstrates parsing with the 'advance' grammar using both 'std::string' (random access iterator) and 'std::list' (bidirectional iterator). This example tests a scenario where the 'advance' operations are expected to succeed. ```c++ unsigned char const alt1[] = { 5, // number of bytes to advance 1, 2, 3, 4, 5, // data to advance through 'b', 'o', 'o', 's', 't', // word to parse 2, // number of bytes to advance 11, 12 // more data to advance through // eoi }; std::string const alt1_string(alt1, alt1 + sizeof alt1); std::list const alt1_list(alt1, alt1 + sizeof alt1); result = qi::parse(alt1_string.begin(), alt1_string.end() , client::advance_grammar()) ? "succeeded" : "failed"; std::cout << "Parsing alt1 using random access iterator " << result << std::endl; result = qi::parse(alt1_list.begin(), alt1_list.end() , client::advance_grammar::const_iterator>()) ? "succeeded" : "failed"; std::cout << "Parsing alt1 using bidirectional iterator " << result << std::endl; ``` -------------------------------- ### C++: Mini XML Tree Printer Implementation Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/qi/mini_xml2_sr Implements a visitor pattern to print the constructed mini XML tree to standard output. `mini_xml_printer` handles elements by printing their tag names and recursively calling itself for children. `mini_xml_node_printer` dispatches to the appropriate printer based on whether a node is an element or text. ```cpp 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; } ``` -------------------------------- ### Include Boost Spirit Distinct Parser Headers Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/example/qi/distinct Includes the necessary Boost Spirit headers for using the qi parser and the distinct parser from the Boost Spirit Repository. These headers provide the core parsing functionality and the distinct keyword parser implementation. ```cpp #include #include ``` -------------------------------- ### Define Token Rules for Lexer in C++ Source: https://www.boost.org/doc/libs/latest/libs/spirit/doc/html/spirit/lex/tutorials/lexer_quickstart2 Associates token definitions like 'word', 'eol', and 'any' with the lexer using a powerful, natural syntax. This method directly assigns rules to 'self' using the '|' operator and leverages semantic actions, freeing the user from explicit token ID definitions. The library internally assigns unique IDs starting from `boost::spirit::lex::min_token_id`. ```C++ this->self = word [++ref(w), ref(c) += distance(_1)] | eol [++ref(c), ++ref(l)] | any [++ref(c)] ; ``` -------------------------------- ### Boost.Spirit.Karma: Example Grammar with Subrules in C++ Source: https://www.boost.org/doc/libs/latest/libs/spirit/repository/doc/html/spirit_repository/karma_components/nonterminal/subrule An example C++ code snippet illustrating the use of Boost.Spirit.Karma subrules within a grammar definition. This specific example, found in `calc2_ast_dump_sr.cpp`, demonstrates how subrules (`ast_node`, `binary_node`, `unary_node`) are assigned to a rule (`entry`), showcasing their ability to be freely mixed with other rules and grammars. ```cpp entry %= ( ast_node %= int_ | binary_node | unary_node , binary_node %= '(' << ast_node << char_ << ast_node << ')' , unary_node %= '(' << char_ << ast_node << ')' ); ```