From 78d622556eea668fc0cf8113fc64ad5329889e53 Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:01:02 +0900 Subject: [PATCH 1/3] Remove boost related assets --- .github/workflows/ci.yml | 1 - build.jam | 48 -- doc/x3/Jamfile | 36 -- doc/x3/abstracts.qbk | 15 - doc/x3/abstracts/attributes.qbk | 197 --------- doc/x3/abstracts/peg.qbk | 107 ----- doc/x3/abstracts/syntax_diagram.qbk | 96 ---- doc/x3/changelog.qbk | 194 -------- doc/x3/html/images/alert.png | Bin 2117 -> 0 bytes doc/x3/html/images/alternative.png | Bin 6643 -> 0 bytes doc/x3/html/images/and_predicate.png | Bin 6598 -> 0 bytes doc/x3/html/images/caution.png | Bin 1400 -> 0 bytes doc/x3/html/images/important.png | Bin 1742 -> 0 bytes doc/x3/html/images/kleene.png | Bin 5388 -> 0 bytes doc/x3/html/images/non-terminal.png | Bin 3380 -> 0 bytes doc/x3/html/images/not_predicate.png | Bin 5489 -> 0 bytes doc/x3/html/images/note.png | Bin 2312 -> 0 bytes doc/x3/html/images/optional.png | Bin 4676 -> 0 bytes doc/x3/html/images/pascal_string.png | Bin 2504 -> 0 bytes doc/x3/html/images/plus.png | Bin 4955 -> 0 bytes doc/x3/html/images/predicate.png | Bin 3477 -> 0 bytes doc/x3/html/images/sequence.png | Bin 5393 -> 0 bytes doc/x3/html/images/start_stop.png | Bin 2338 -> 0 bytes doc/x3/html/images/terminal.png | Bin 3691 -> 0 bytes doc/x3/html/images/tip.png | Bin 2605 -> 0 bytes doc/x3/include.qbk | 29 -- doc/x3/introduction.qbk | 95 ---- doc/x3/preface.qbk | 75 ---- doc/x3/quick_reference.qbk | 372 ---------------- doc/x3/spirit_x3.qbk | 248 ----------- doc/x3/tutorial/actions.qbk | 90 ---- doc/x3/tutorial/annotation.qbk | 417 ------------------ doc/x3/tutorial/complex.qbk | 80 ---- doc/x3/tutorial/employee.qbk | 223 ---------- doc/x3/tutorial/error_handling.qbk | 349 --------------- doc/x3/tutorial/minimal.qbk | 240 ---------- doc/x3/tutorial/non_throwing_expectations.qbk | 97 ---- doc/x3/tutorial/num_list2.qbk | 49 -- doc/x3/tutorial/num_list3.qbk | 55 --- doc/x3/tutorial/num_list4.qbk | 71 --- doc/x3/tutorial/rexpr.qbk | 211 --------- doc/x3/tutorial/roman.qbk | 264 ----------- doc/x3/tutorial/sum_tutorial.qbk | 75 ---- doc/x3/tutorial/tutorial_intro.qbk | 42 -- doc/x3/tutorial/warming_up.qbk | 155 ------- meta/explicit-failures-markup.xml | 24 - meta/libraries.json | 22 - sublibs | 1 - test/Jamfile | 22 - test/x4/Jamfile | 131 ------ 50 files changed, 4131 deletions(-) delete mode 100644 build.jam delete mode 100644 doc/x3/Jamfile delete mode 100644 doc/x3/abstracts.qbk delete mode 100644 doc/x3/abstracts/attributes.qbk delete mode 100644 doc/x3/abstracts/peg.qbk delete mode 100644 doc/x3/abstracts/syntax_diagram.qbk delete mode 100644 doc/x3/changelog.qbk delete mode 100644 doc/x3/html/images/alert.png delete mode 100644 doc/x3/html/images/alternative.png delete mode 100644 doc/x3/html/images/and_predicate.png delete mode 100644 doc/x3/html/images/caution.png delete mode 100644 doc/x3/html/images/important.png delete mode 100644 doc/x3/html/images/kleene.png delete mode 100644 doc/x3/html/images/non-terminal.png delete mode 100644 doc/x3/html/images/not_predicate.png delete mode 100644 doc/x3/html/images/note.png delete mode 100644 doc/x3/html/images/optional.png delete mode 100644 doc/x3/html/images/pascal_string.png delete mode 100644 doc/x3/html/images/plus.png delete mode 100644 doc/x3/html/images/predicate.png delete mode 100644 doc/x3/html/images/sequence.png delete mode 100644 doc/x3/html/images/start_stop.png delete mode 100644 doc/x3/html/images/terminal.png delete mode 100644 doc/x3/html/images/tip.png delete mode 100644 doc/x3/include.qbk delete mode 100644 doc/x3/introduction.qbk delete mode 100644 doc/x3/preface.qbk delete mode 100644 doc/x3/quick_reference.qbk delete mode 100644 doc/x3/spirit_x3.qbk delete mode 100644 doc/x3/tutorial/actions.qbk delete mode 100644 doc/x3/tutorial/annotation.qbk delete mode 100644 doc/x3/tutorial/complex.qbk delete mode 100644 doc/x3/tutorial/employee.qbk delete mode 100644 doc/x3/tutorial/error_handling.qbk delete mode 100644 doc/x3/tutorial/minimal.qbk delete mode 100644 doc/x3/tutorial/non_throwing_expectations.qbk delete mode 100644 doc/x3/tutorial/num_list2.qbk delete mode 100644 doc/x3/tutorial/num_list3.qbk delete mode 100644 doc/x3/tutorial/num_list4.qbk delete mode 100644 doc/x3/tutorial/rexpr.qbk delete mode 100644 doc/x3/tutorial/roman.qbk delete mode 100644 doc/x3/tutorial/sum_tutorial.qbk delete mode 100644 doc/x3/tutorial/tutorial_intro.qbk delete mode 100644 doc/x3/tutorial/warming_up.qbk delete mode 100644 meta/explicit-failures-markup.xml delete mode 100644 meta/libraries.json delete mode 100644 sublibs delete mode 100644 test/Jamfile delete mode 100644 test/x4/Jamfile diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64d20df71..870b41d3c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,6 @@ jobs: - 'include/boost/spirit/x4/**/*' - 'include/boost/spirit/x4.hpp' - 'test/x4/**/*' - - '!**/Jamfile' build: name: "[${{ matrix.cpp_version.name }}] ${{ matrix.spirit_component }} | ${{ matrix.compiler.toolset }}-${{ matrix.compiler.version }} (${{ matrix.build_type.name }}) @ ${{ matrix.os.name }}-${{ matrix.os.version }}" diff --git a/build.jam b/build.jam deleted file mode 100644 index 11570f1e5..000000000 --- a/build.jam +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright René Ferdinand Rivera Morell 2023-2024 -# Copyright (c) 2021 Nikita Kniazev -# Copyright (c) 2025 Nana Sakisaka -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -require-b2 5.2 ; - -constant boost_dependencies : - /boost/assert//boost_assert - /boost/config//boost_config - /boost/core//boost_core - /boost/endian//boost_endian - /boost/function//boost_function - /boost/function_types//boost_function_types - /boost/fusion//boost_fusion - /boost/integer//boost_integer - /boost/io//boost_io - /boost/mpl//boost_mpl - /boost/preprocessor//boost_preprocessor - /boost/static_assert//boost_static_assert - /boost/throw_exception//boost_throw_exception - /boost/type_traits//boost_type_traits - /boost/typeof//boost_typeof - /boost/utility//boost_utility - /boost/variant//boost_variant ; - -project /boost/spirit_x4 - : common-requirements - include - : requirements - # Enable additional useful warnings - extra,gcc:-Wshadow-local - extra,clang-linux:-Wshadow-field-in-constructor - extra,clang-linux:-Wshadow-uncaptured-local - extra,clang-linux:-Wundefined-reinterpret-cast - extra,msvc:-w44555 # result of expression not used - ; - -explicit - [ alias boost_spirit_x4 : : : : $(boost_dependencies) ] - [ alias all : boost_spirit_x4 test ] - ; - -call-if : boost-library spirit_x4 - ; - diff --git a/doc/x3/Jamfile b/doc/x3/Jamfile deleted file mode 100644 index 2c801364b..000000000 --- a/doc/x3/Jamfile +++ /dev/null @@ -1,36 +0,0 @@ -#============================================================================== -# Copyright (c) 2001-2015 Joel de Guzman -# Copyright (c) 2001-2011 Hartmut Kaiser -# -# Use, modification and distribution is subject to the Boost Software -# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) -#============================================================================== - -project spirit_x3/doc ; - -import boostbook ; -import quickbook ; -import modules ; - -path-constant here : . ; - -path-constant images_location : html ; - -boostbook spirit_x3 - : - spirit_x3.qbk - : - boost.root=../../../../.. - chunk.section.depth=4 - chunk.first.sections=1 - toc.section.depth=3 - toc.max.depth=3 - generate.section.toc.level=4 - html:admon.graphics.path=images/ - - . - pdf:img.src.path=$(images_location)/ - pdf:draft.mode="no" - pdf:"boost.url.prefix=http://www.boost.org/doc/libs/release/libs/spirit/doc/html" - ; diff --git a/doc/x3/abstracts.qbk b/doc/x3/abstracts.qbk deleted file mode 100644 index 70575e7cf..000000000 --- a/doc/x3/abstracts.qbk +++ /dev/null @@ -1,15 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Abstracts] - -[include abstracts/syntax_diagram.qbk] -[include abstracts/peg.qbk] -[include abstracts/attributes.qbk] - -[endsect] diff --git a/doc/x3/abstracts/attributes.qbk b/doc/x3/abstracts/attributes.qbk deleted file mode 100644 index edb0cf7c6..000000000 --- a/doc/x3/abstracts/attributes.qbk +++ /dev/null @@ -1,197 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[/////////////////////////////////////////////////////////////////////////////] -[section:primitive_attributes Attributes of Primitive Components] - -Parsers in __spirit__ are fully attributed. __x3__ parsers always /expose/ an -attribute specific to their type. This is called /synthesized attribute/ as it -is returned from a successful match representing the matched input sequence. For -instance, numeric parsers, such as `int_` or `double_`, return the `int` or -`double` value converted from the matched input sequence. Other primitive parser -components have other intuitive attribute types, such as for instance `int_` -which has `int`, or `ascii::char_` which has `char`. Primitive parsers apply the -normal C++ convertibility rules: you can use any C++ type to receive the parsed -value as long as the attribute type of the parser is convertible to the type -provided. The following example shows how a synthesized parser attribute (the -`int` value) is extracted by calling the API function `x3::parse`: - - int value = 0; - std::string str("123"); - std::string::iterator strbegin = str.begin(); - x3::parse(strbegin, str.end(), int_, value); // value == 123 - -For a full list of available parser primitives and their attribute types please -see the sections __sec_x3_primitive__. - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:compound_attributes Attributes of Compound Components] - -__x3__ implement well defined attribute type propagation rules for all compound -parsers, such as sequences, alternatives, Kleene star, etc. The main attribute -propagation rule for a sequences is for instance: - - a: A, b: B --> (a >> b): tuple - -which reads as: - -[:Given `a` and `b` are parsers, and `A` is the attribute type of `a`, and `B` -is the attribute type of `b`, then the attribute type of `a >> b` (`a << b`) -will be `tuple`.] - -[note The notation `tuple` is used as a placeholder expression for any - fusion sequence holding the types A and B, such as `boost::fusion::tuple` - or `std::pair` (for more information see __fusion__).] - -As you can see, in order for a type to be compatible with the attribute type -of a compound expression it has to - -* either be convertible to the attribute type, -* or it has to expose certain functionalities, i.e. it needs to conform to a - concept compatible with the component. - -Each compound component implements its own set of attribute propagation rules. -For a full list of how the different compound parsers consume attributes -see the sections __sec_x3_compound__. - -[heading The Attribute of Sequence Parsers] - -Sequences require an attribute type to expose the concept of a fusion sequence, -where all elements of that fusion sequence have to be compatible with the -corresponding element of the component sequence. For example, the expression: - - double_ >> double_ - -is compatible with any fusion sequence holding two types, where both types have -to be compatible with `double`. The first element of the fusion sequence has to -be compatible with the attribute of the first `double_`, and the second element -of the fusion sequence has to be compatible with the attribute of the second -`double_`. If we assume to have an instance of a `std::pair`, -we can directly use the expressions above to do both, parse input to fill the -attribute: - - // the following parses "1.0 2.0" into a pair of double - std::string input("1.0 2.0"); - std::string::iterator strbegin = input.begin(); - std::pair p; - x3::phrase_parse(strbegin, input.end(), - x3::double_ >> x3::double_, // parser grammar - x3::space, // delimiter grammar - p); // attribute to fill while parsing - -[tip *For sequences only:* To keep it simple, unlike __Spirit.qi__, __x3__ does - not support more than one attribute anymore in the `parse` and `phrase_parse` function. - Just use `std:tuple'. Be sure to include `boost/fusion/adapted/std_tuple.hpp' in this case. - -] - -[heading The Attribute of Alternative Parsers] - -Alternative parsers are all about - well - alternatives. In -order to store possibly different result (attribute) types from the different -alternatives we use the data type __boost_variant__. The main attribute -propagation rule of these components is: - - a: A, b: B --> (a | b): variant - -Alternatives have a second very important attribute propagation rule: - - a: A, b: A --> (a | b): A - -often simplifying things significantly. If all sub expressions of -an alternative expose the same attribute type, the overall alternative -will expose exactly the same attribute type as well. - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:more_compound_attributes More About Attributes of Compound Components] - -While parsing input, it is often desirable to combine some -constant elements with variable parts. For instance, let us look at the example -of parsing or formatting a complex number, which is written as `(real, imag)`, -where `real` and `imag` are the variables representing the real and imaginary -parts of our complex number. This can be achieved by writing: - - '(' >> double_ >> ", " >> double_ >> ')' - -Literals (such as `'('` and `", "`) do /not/ expose any attribute -(well actually, they do expose the special type `unused_type`, but in this -context `unused_type` is interpreted as if the component does not expose any -attribute at all). It is very important to understand that the literals don't -consume any of the elements of a fusion sequence passed to this component -sequence. As said, they just don't expose any attribute and don't produce -(consume) any data. The following example shows this: - - // the following parses "(1.0, 2.0)" into a pair of double - std::string input("(1.0, 2.0)"); - std::string::iterator strbegin = input.begin(); - std::pair p; - x3::parse(strbegin, input.end(), - '(' >> x3::double_ >> ", " >> x3::double_ >> ')', // parser grammar - p); // attribute to fill while parsing - -where the first element of the pair passed in as the data to generate is still -associated with the first `double_`, and the second element is associated with -the second `double_` parser. - -This behavior should be familiar as it conforms to the way other input and -output formatting libraries such as `scanf`, `printf` or `boost::format` are -handling their variable parts. In this context you can think about __x3__'s -primitive components (such as the `double_` above) as of being -type safe placeholders for the attribute values. - -[tip *For sequences only:* To keep it simple, unlike __Spirit.qi__, __x3__ does - not support more than one attribute anymore in the `parse` and `phrase_parse` function. - Just use `std:tuple'. Be sure to include `boost/fusion/adapted/std_tuple.hpp' in this case. - -] - -Let's take a look at this from a more formal perspective: - - a: A, b: Unused --> (a >> b): A - -which reads as: - -[:Given `a` and `b` are parsers, and `A` is the attribute type of - `a`, and `unused_type` is the attribute type of `b`, then the attribute type - of `a >> b` (`a << b`) will be `A` as well. This rule applies regardless of - the position the element exposing the `unused_type` is at.] - -This rule is the key to the understanding of the attribute handling in -sequences as soon as literals are involved. It is as if elements with -`unused_type` attributes 'disappeared' during attribute propagation. Notably, -this is not only true for sequences but for any compound components. For -instance, for alternative components the corresponding rule is: - - a: A, b: Unused --> (a | b): A - -again, allowing to simplify the overall attribute type of an expression. - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:nonterminal_attributes Attributes of Nonterminals] - -Nonterminals are the main means of constructing more complex parsers out of -simpler ones. The nonterminals in the parser world are very similar to functions -in an imperative programming language. They can be used to encapsulate parser -expressions for a particular input sequence. After being defined, the -nonterminals can be used as 'normal' parsers in more complex expressions -whenever the encapsulated input needs to be recognized. Parser nonterminals in -__x3__ usually return a value (the synthesized attribute). - -The type of the synthesized attribute as to be explicitly specified while -defining the particular nonterminal. Example (ignore ID for now): - - x3::rule r; - -[endsect] - diff --git a/doc/x3/abstracts/peg.qbk b/doc/x3/abstracts/peg.qbk deleted file mode 100644 index 2fc36264e..000000000 --- a/doc/x3/abstracts/peg.qbk +++ /dev/null @@ -1,107 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] -[section Parsing Expression Grammar] - -Parsing Expression Grammars (PEG) [footnote Bryan Ford: Parsing Expression -Grammars: A Recognition-Based Syntactic Foundation, -[@http://pdos.csail.mit.edu/~baford/packrat/popl04/]] are a derivative of -Extended Backus-Naur Form (EBNF) [footnote Richard E. Pattis: EBNF: A Notation -to Describe Syntax, [@http://www.cs.cmu.edu/~pattis/misc/ebnf.pdf]] -with a different interpretation, designed to represent a recursive descent -parser. A PEG can be directly represented as a recursive-descent parser. - -Like EBNF, PEG is a formal grammar for describing a formal language in -terms of a set of rules used to recognize strings of this language. -Unlike EBNF, PEGs have an exact interpretation. There is only one valid -parse tree (see __ast__) for each PEG grammar. - -[heading Sequences] - -Sequences are represented by juxtaposition like in EBNF: - - a b - -The PEG expression above states that, in order for this to succeed, -`b` must follow `a`. Here's the syntax diagram: - -[:__sd_sequence__] - -Here's a trivial example: - - 'x' digit - -which means the character `x` must be followed by a digit. - -[note In __x3__, we use the `>>` for sequences since C++ does not -allow juxtaposition.] - -[heading Alternatives] - -Alternatives are represented in PEG using the slash: - - a / b - -[note In __x3__, we use the `|` for alternatives just as in EBNF.] - -Alternatives allow for choices. The expression above reads: try to match -`a`. If `a` succeeds, success, if not try to match `b`. This is a bit of -a deviation from the usual EBNF interpretation where you simply match -`a` *or* `b`. Here's the syntax diagram: - -[:__sd_choice__] - -PEGs allow for ambiguity in the alternatives. In the expression above, -both `a` or `b` can both match an input string. However, only the first -matching alternative is valid. As noted, there can only be one valid -parse tree. [/FIXME: $$$ explain more about this $$$] - -[heading Loops] - -Again, like EBNF, PEG uses the regular-expression Kleene star and the -plus loops: - - a* - a+ - -[note __x3__ uses the prefix star and plus since there is no postfix star or -plus in C++.] - -Here are the syntax diagrams: - -[:__sd_kleene__] -[:__sd_plus__] - -The first, called the Kleene star, matches zero or more of its subject -`a`. The second, plus, matches one ore more of its subject `a`. - -Unlike EBNF, PEGs have greedy loops. It will match as much as it can -until its subject fails to match without regard to what follows. The following -is a classic example of a fairly common EBNF/regex expression failing to match -in PEG: - - alnum* digit - -In PEG, alnum will eat as much alpha-numeric characters as it can -leaving nothing more left behind. Thus, the trailing digit will get -nothing. Loops are simply implemented in recursive descent code as for/while -loops making them extremely efficient. That is a definite advantage. On the -other hand, those who are familiar with EBNF and regex behavior might find the -behavior a major gotcha. PEG provides a couple of other mechanisms to circumvent -this. We will see more of these other mechanisms shortly. - -[heading Difference] - -In some cases, you may want to restrict a certain expression. You can think of a -PEG expression as a match for a potentially infinite set of strings. The -difference operator allows you to restrict this set: - - a - b - -The expression reads: match `a` but not `b`. - -[endsect] diff --git a/doc/x3/abstracts/syntax_diagram.qbk b/doc/x3/abstracts/syntax_diagram.qbk deleted file mode 100644 index 3b15c0649..000000000 --- a/doc/x3/abstracts/syntax_diagram.qbk +++ /dev/null @@ -1,96 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] -[section Syntax Diagram] - -In the next section, we will deal with Parsing Expression Grammars -(PEG) [footnote Bryan Ford: Parsing Expression Grammars: A Recognition-Based -Syntactic Foundation, [@http://pdos.csail.mit.edu/~baford/packrat/popl04/]], -a variant of Extended Backus-Naur Form (EBNF) [footnote Richard E. Pattis: EBNF: -A Notation to Describe Syntax, [@http://www.cs.cmu.edu/~pattis/misc/ebnf.pdf]] -with a different interpretation. It is easier to understand PEG using Syntax -Diagrams. Syntax diagrams represent a grammar graphically. It was used -extensively by Niklaus Wirth [footnote Niklaus Wirth: The Programming Language -Pascal. (July 1973)] in the "Pascal User Manual". Syntax Diagrams are easily -understandable by programmers due to their similarity to flow charts. The -isomorphism of the diagrams and functions make them ideal for representing -__rd__ parsers which are essentially mutually recursive functions. - -[heading Elements] - -All diagrams have one entry and one exit point. Arrows connect all possible -paths through the grammar from the entry point to the exit point. - -[:__sd_start_stop__] - -Terminals are represented by round boxes. Terminals are atomic and -usually represent plain characters, strings or tokens. - -[:__sd_terminals__] - -Non-terminals are represented by boxes. Diagrams are modularized using -named non-terminals. A complex diagram can be broken down into a set of -non-terminals. Non-terminals also allow recursion (i.e. a non-terminal can call -itself). - -[:__sd_non_terminals__] - -[heading Constructs] - -The most basic composition is the Sequence. B follows A: - -[:__sd_sequence__] - -The ordered choice henceforth we will call /alternatives/. In PEG, ordered -choice and alternatives are not quite the same. PEG allows ambiguity of choice -where one or more branches can succeed. In PEG, in case of ambiguity, the first -one always wins. - -[:__sd_choice__] - -The optional (zero-or-one): - -[:__sd_optional__] - -Now, the loops. We have the zero-or-more and one-or-more: - -[:__sd_kleene__] -[:__sd_plus__] - -Take note that, as in PEG, these loops behave greedily. If there is -another 'A' just before the end-point, it will always fail because the -preceding loop has already exhausted all 'A's and there is nothing more left. -This is a crucial difference between PEG and general Context Free Grammars -(CFGs). This behavior is quite obvious with syntax diagrams as they resemble -flow-charts. - -[heading Predicates] - -Now, the following are Syntax Diagram versions of PEG predicates. These are not -traditionally found in Syntax Diagrams. These are special extensions we invented -to closely follow PEGs. - -First, we introduce a new element, the Predicate: - -[:__sd_predicate__] - -This is similar to the conditionals in flow charts where the 'No' branch is -absent and always signals a failed parse. - -We have two versions of the predicate, the /And-Predicate/ and the -/Not-Predicate/: - -[:__sd_and_predicate__] -[:__sd_not_predicate__] - -The /And-Predicate/ tries the predicate, P, and succeeds if P succeeds, -or otherwise fail. The opposite is true with the /Not-Predicate/. It -tries the predicate, P, and fails if P succeeds, or otherwise succeeds. Both -versions do a look-ahead but do not consume any input regardless if P succeeds -or not. - -[endsect] diff --git a/doc/x3/changelog.qbk b/doc/x3/changelog.qbk deleted file mode 100644 index 53338890e..000000000 --- a/doc/x3/changelog.qbk +++ /dev/null @@ -1,194 +0,0 @@ -[/============================================================================== - Copyright (C) 2018-2021 Nikita Kniazev - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -===============================================================================/] - -[section Changelog] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_10 Spirit V3.10 (Boost V1.78.0)] - -* Fortified against `min` and `max` macros. [gh_pr 697] -* Producing a variant attribute in an alternative parser branch was leading to a - compilation error when parsed into a superset variant attribute due to - swapped parameters to `is_substitute` trait. [gh_pr 702] [gh 701] [gh 679] - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_9 Spirit V3.0.9 (Boost V1.77.0)] - -*Breaking change*: Optional parser no longer unflattens sequence, parsers like - `int_ >> -(int_ >> int_)` into `tuple, optional>` - will produce a compilation error in sequence parser. This was a bugfeature - which might be reimplemented in the future. - -* Fixed list parser with attribute-less subject in sequence parser. [gh_pr 663] -* Fixed optional parser with container attribute in sequence parser. [gh_pr 665] -* Fixed `error_handler` newline/whitespace handling issues. [gh_pr 669] [gh_pr 670] -* Fixed `seek[...]` directive going past the end of input introduced in [gh_pr 30], - triggered when pre-skip leaves no data. [gh_pr 658] [gh_pr 683] -* Removed rollback in rules to fix a regression introduced in [gh_pr 670]. [gh_pr 686] - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_8 Spirit V3.0.8 (Boost V1.76.0)] - -* Fixed assertion in standard parser with an input containing characters from - extended charset (on values above 0x7F) [gh_pr 620] -* Enhanced debug output to print unicode code points as hex [gh_pr 634] -* Skip rule definition binder creation in `parse_rule` [gh_pr 646] -* Replaced Boost.Math with std alternatives [gh_pr 648] -* Fixed unqualified `get` call in `parse_rule` -* Removed unused header `no_case_string_parse.hpp` -* Make literal binary parser constructor non-templated -* Fixed unqualified `get` call in `annotate_on_success::on_success` [gh 526] -* Fixed multiple times missed `force_attribute` parameter. Adresses compilation - errors and slow compilation due to rule definition injection into context - when `force_attribute` is set to `true` [gh_pr 651] -* Skip rule definition injection into context when a rule placeholder constructed - and immediately consumed (like `auto const grammar = rule{} = parser`) [gh_pr 650] - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_7 Spirit V3.0.7 (Boost V1.74.0)] - -* Ceased dependence on Boost.Locale (replaced `locale::conv::utf_to_utf` - with `x3::to_utf8`), and Boost.Filesystem [gh_pr 596] -* Fixed infinity recursion in `is_substitute` trait that was blocking recursive - sequences via containers [gh 461] [gh_pr 606] -* Fixed sequence parser in alternative into container [gh 434] [gh_pr 605] -* Fixed some corner cases in alternative parser with container attribute, - notably atribute-less parsers in alternative parser with container attribute - were appending an empty value [gh 394] [gh 603] [gh_pr 604] -* Attribute type of alternative/sequence parsers now calculated without MPL, - what removes MPL limits on alternative/sequence parser chain length [gh 515] [gh_pr 607] -* Reverted [gh_pr 534] that made possible parsing `optional` into `T` [gh_pr 608] -* Removed unneeded `reserve` before `insert` [gh_pr 611] -* Removed `value_initialize` trait [gh_pr 613] -* Removed unwanted move due to wrong `pseudo_attribute` usage, that was also - causing bogus GCC `-Wununinitlized` warning [gh_pr 613] -* Removed unused `boost/spirit/home/x3/support/utility/unrefcv.hpp` header - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_6 Spirit V3.0.6 (Boost V1.73.0)] - -* ADL used to find and match `unused_type` streaming operators for every type - in `boost::spirit::x3` namespace [gh_pr 553] [gh 552] -* Ceased dependence on Boost.TTI -* Rule placeholders now a non-trivial type because its copy constructor checks - for a static initialization fiasco [gh_pr 571] -* Most parsers are now constexpr-constructible [gh_pr 570] - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_5 Spirit V3.0.5 (Boost V1.72.0)] - -* `any_char` parser were accepting characters outside of encoding. [gh 520] [gh_pr 521] sehe -* Added workaround `move_to` overload for `boost::optional` type. [gh 533] [gh_pr 534] Duzy Chan -* Unicode out-of-bounds category lookup. [gh_pr 528] Christian Mazakas -* Mismatched pragma warning push/pop in `escape_char.ipp`. [gh 532] [gh_pr 535] stefan301 -* Remove bool->char->bool conversion in `[no_]case_compare`. [gh_pr 536] -* `` functions were called with negative values. [gh_pr 543] -* Fixed `parse_rule` definition check. [gh_pr 549] (regressed in [gh_pr 457]) - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_4_boost_1_71 Spirit V3.0.4 (Boost V1.71.0)] - -* Explicitly delete all non implemented assignment operators. [gh_pr 489] Romain Geissler -* Unpublish `x3/support/utility/testing.hpp`. [gh_pr 492] -* Removed unused `is_char` and `is_string` traits. [gh_pr 507] -* Simplified `string_traits`. [gh_pr 507] -* `raw` parser attribute materialization issue. [gh 509] -* Removed static assert guarding unwanted attribute materialization that - happens when rule parser producing an attribute called without an actual - attribute. See [gh 511] for the discussion. - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_4 Spirit V3.0.4 (Boost V1.70.0)] - -* Integer parsers should now handle user defined types. [gh_pr 429] -*[/^] [*Note:] The `check_overflow` trait default implementation now relies on - `std::numeric_limits::is_bounded` instead of `boost::integer_traits::is_integral`. -* Removed use of deprecated `boost/detail/iterator.hpp` header. [gh_pr 432] -* Removed sequence into plain parsing. Now it triggers a compile time error - instead of silently parsing the the sequence and taking the last value as a result. [gh_pr 439] -* Fixed `parse_rule` instantiation with `BOOST_SPIRIT_INSTANTIATE` when: - * A rule has no attribute. [gh_pr 455] - * An actual attribute is not of type a rule was declared with. [gh_pr 456] [gh 457] -*[/^] A [*huge] thanks goes out to [@https://github.com/Xeverous Xeverous] - for reporting a regression in [gh 453]. -* Fixed unneeded attribute synthesization and no-transformation attribute - reference pass-through in rules. [gh 444] [gh_pr 449] [gh_pr 452] -* Removed broken 1.0#INF parser. It was poorly documented and never worked. [gh 415] [gh_pr 458] [trac 8699] -* The undocumented `make_attribute` trait was removed due to bugs [gh_pr 449] - and to simplify attribute transformation. [gh_pr 460] -*[/^] If you were using it to workaround bugs in attribute transformation - - they should not be needed anymore as of this release. -* The integer value parser now respects `std::numeric_limits::digits10` value. [gh_pr 469] -* Fixed underflow check for a `(Min % Base) == 0` corner case. [gh_pr 469] -* Fixed an output value on overflow of `IgnoreOverflowDigits=true` integer parser. [gh_pr 470] -* Container attribute elements were copyied, but not moved. [gh_pr 472] -* Special handling of references in `transform_attribute` was removed. [gh_pr 480] - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_3 Spirit V3.0.3 (Boost V1.69.0)] - -* Drop own FP routines in favor of `boost::math`. [gh_pr 392] [trac 13531] -* Missing visibility mark on exception types. [gh_pr 409] -* to_utf8: Fixed `wchar_t` handling on Windows. [gh_pr 413] [gh 395] - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_2 Spirit V3.0.2 (Boost V1.68.0)] - -* Small list parser optimization. [gh_pr 368] -* Pass container attributes through sequence parser or unary - ending down to a sequence parser. [gh_pr 370] [trac 12085] -* More fine grained sequence attribute check message. [gh_pr 371] -* Removed redundant check in `skip_over`. [gh_pr 373] -* Workaround constexpr in noexcept VS2015 bug in entire `x3::variant`. [gh_pr 379] -* Fixed `calc4b` example compilation. [gh_pr 384] -* Minor code improvements. [gh_pr 374] - -[endsect] - -[/////////////////////////////////////////////////////////////////////////////] -[section:spirit_3_0_1 Spirit V3.0.1 (Boost V1.67.0)] - -There was no version bump and changelog for Boost V1.56.0-1.66.0 releases. - -* Removed `with_context`. [gh_pr 239] -* Added noexcept to `x3::variant` and `forward_ast`. [gh_pr 241] -* CR+LF lines wrongly counted in `error_handler::position()`. [gh_pr 248] -* Fixed `unused_type` attribute case in `parse_into_container`. [gh_pr 266] -* Fixed parsing into associative containers. [gh_pr 289] -* Fixed overflow problem in `uint_parser`. [gh_pr 297] -* Added VS2015 Update 3 support by using workarounds. [gh_pr 308] -* Fixed include guard names collision with Qi. [gh_pr 313] -* Added parsing into range. [gh_pr 316] [trac 12928] -* Changed iterator concept static assert from `ForwardIterator` to - `ReadableIteratorConcept && ForwardTraversalConcept`. [gh_pr 320] -* Reenabled `fusion::map` support. [gh_pr 330] -* Fixed `string("...")` and `attr("...")` to single item sequence. [gh_pr 337] -* Dereference a single item view instead of unwrapping sequence. [gh_pr 340] -* Prevent `parse_nan` from dereferencing out of range iterator. [gh_pr 351] -* Use traits to test if container is empty. [gh_pr 355] - -[endsect] - -[endsect] diff --git a/doc/x3/html/images/alert.png b/doc/x3/html/images/alert.png deleted file mode 100644 index 101b5f780bef6b4e28e5c4c528917743014cf195..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2117 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 F{vV(|^9uj~ diff --git a/doc/x3/html/images/and_predicate.png b/doc/x3/html/images/and_predicate.png deleted file mode 100644 index 761052cc908889d37f33cc6ac6cacfeb3b3dce9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6598 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 CaJ@qS diff --git a/doc/x3/html/images/caution.png b/doc/x3/html/images/caution.png deleted file mode 100644 index 4be6d07237c70f92024fa479896a55331cbb5027..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1400 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 diff --git a/doc/x3/html/images/non-terminal.png b/doc/x3/html/images/non-terminal.png deleted file mode 100644 index 3ff530e2f8b78081ac8ec22d0c1178587c9a289c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3380 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 DrH7hl diff --git a/doc/x3/html/images/predicate.png b/doc/x3/html/images/predicate.png deleted file mode 100644 index 81740707f9505f51eaea73eb772218d156a854de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3477 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 D!;5Fv diff --git a/doc/x3/html/images/sequence.png b/doc/x3/html/images/sequence.png deleted file mode 100644 index 481519793f7c8296ff83ec11d8f7403fd0cccf4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5393 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 diff --git a/doc/x3/html/images/start_stop.png b/doc/x3/html/images/start_stop.png deleted file mode 100644 index 8680f24c29461d2e6b33770589d98d4c5c404178..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2338 zcmV+-3ElRIP)AW#^LpT+j2 z(9-gj9{)J!p-&&4w{1dR-WSu8-1L3UJ@?-8e4q1t@45Fr6;&nIA|e7LDk>`KYHDg$ zB$LTxNl8g*OH0ee=H}+3hYlV3A@E(;F+udS_p3U~mxhrUsqw~{k} z1KuqwE1TWW&`>jweR+8~W5$e00+TVCr~*a;!-0hNmv@ru2u@U2SI?a`ZQ7usaO%{l z!+~00JO*$X4siBdygA9WW0Fp%FQihbK^dPve_k+9M*|f=DZKy>MQ}s}NE|zMtZ~<_ zU7dqz(A3lf2Iw7LM&OfNww%0K$#n$N)6=te?b@{`(&==+cH6ga=g5&G-4S)(0vkv! z0ah?Dy1Kgan>TOP*49>3m8Pa9Rz8EC^+bmxH<;4*O4`^ig?#S{Kp zKd`517>`x}6M%;b3kw%iR#r|aDk{3OrKLqvsZ=)>sqMfy;0UnK%TeG0aD_ZwHs=gr zxDN6#Y{D81OvKW#dx08Y6gH`)fs4Q?4B!J8xMzV&Ksq161t`q51K6g`73|e7@as0< zG*C`2z$pyS6TnFKRW2MFjEG2)h|Cs|@|e02BJ!Y!OvsCKy3i5&H-KaG?$avJ3~T^K#T>aO zfUjloNPj#qFGJnq*kYq9q^kq=W6SEm|4YDI!22`wvj7;I)lUhz+I6x0*nD>10MmBG5wD4w!^W_osVI=XQjZW+@}}aW<;pnWUrg$ z*Z2DMwtjAMo7;@_>m=}s>plUDj%kwwK8}5^bw^CSxNoI?UFr8*76tfWA83DEM{aaC zQ0%`))0d|e*dDTd4BNAf+H3=ALUs#XzX&+)zdM0n$FyA-YPTHQFCG?pQ0*9{jLYDE z889*u@!|eELUlF3?<4isfS-r)!43lycmeoL$Tp4f{~fQC>6y&ePbIp83$2H1j~Xnfo2HhBNZP`keZe~9?B#_hX- zH-W`Kc|Q?73)tjszKQcQw)ecp^*_a;ccx>az}6UmuVD208Ej%+itSzR0g40TV&Hf5 zoq^kdKVjKLX^fLMa4_(ax1AT!kM<}y8w2oZB3TLH?mK@n^OB9QfZ2?7$|w zF){Wxa4_(U>wXerztQVH7Xes-ha6Y&It^%n~exTkla7_EFbiKV5f)-XJ9E3k!2#XUPRu;UYEVV`-uM%vS|=~2C@J+psMf2RjO)- zs%}!%1|M%4mbR4xTSR2a0R2w}E~@Ien7Tv$w>E=5>_;c?9`M10h%|`ElQBkVRc%z& zdW`h%!e-ozA|j7s6UZ814wgSZ1AGWO1&)(T{q-4<`M?{IG3!O-X%QJ2@n2PSpQ=8I z(L@6H>;U~2W0O>z1c$4`BKj-+by$ckC?<%=o2q&^gWXQx3mA#_C$C~WIbT(`21;MD zR&x`FtRiwB_FeEBk*Y<&moQ5BZHDGM{qI2j{|ES}h>TR#=!3t<|DK8HZ}{|9M22B$ z>edACN7p|uBBe3L#lRQ+a!aVH6DSPU`yw(5xDPlP2G?aK#*YOeG8mA9j{(EcvH**g z#)xg;|Fa@8F2;WWzUr5o2N)xG5KCfw`nvz!7SYcYkz_=-2n(h?UBjy9upSvF!lG=xna`=F4ZWY-EXFR{|?B>S)AsVftnfJFws? z_OV;sm#Sc}aoE$1Cip?Rvohw!K2PsAVW(YJPjB|o?oM?8D}bN5e&!$m7U1t8A68(| z`>hPwLn)RbhSSV&d5uV3kNuxVI8&-|{R8yo!abq-t;8=h{t5g$Vt)ir-TIu#iAW8$ zWUY2*_W*CJY6meQB9njzfy)6ch)5;2{!e0?N4r(^tZ#qT0!LN#q=;1b%`~a%iI~2N zfazE^a0*)?{!&#>#rfiGMq!!HSnLhj2kcSRmJIe)K1Kp~E8tzHvFX4R?Con*)#jM7 zTCtS&%Z}SbV27%{bKNcs@Q@5%!T_sk#_VM1L?g>G1aOw+f21lujpovMga7~l07*qo IM6N<$f^=h7z5oCK diff --git a/doc/x3/html/images/terminal.png b/doc/x3/html/images/terminal.png deleted file mode 100644 index f688adb1851d2e9f8ade44d9ff63268a7268c01d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3691 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 - -To distinguish between Spirit versions, you can inspect the version file: - - #include - -using the preprocessor define - - SPIRIT_X3_VERSION - -It is a hex number where the first two digits determine the major version while -the last two digits determine the minor version. For example: - - #define SPIRIT_X3_VERSION 0x3010 // version 3.10 - -[endsect] [/Include] diff --git a/doc/x3/introduction.qbk b/doc/x3/introduction.qbk deleted file mode 100644 index 0d643dc5d..000000000 --- a/doc/x3/introduction.qbk +++ /dev/null @@ -1,95 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Introduction] - -Boost Spirit X3 is an object-oriented, recursive-descent parser for C++. It -allows you to write grammars using a format similar to -Extended Backus Naur Form (EBNF)[footnote -[@http://www.cl.cam.ac.uk/%7Emgk25/iso-14977.pdf ISO-EBNF]] directly in C++. -These inline grammar specifications can mix freely with other C++ code and, -thanks to the generative power of C++ templates, are immediately executable. -Conventional compiler-compilers or parser-generators have to perform an -additional translation step from the source EBNF code to C or C++ code. - -Since the target input grammars are written entirely in C++ we do not need any -separate tools to compile, preprocess or integrate those into the build process. -__spirit__ allows seamless integration of the parsing process with other C++ -code. This often allows for simpler and more efficient code. - -The created parsers are fully attributed, which allows you to easily build and -handle hierarchical data structures in memory. These data structures resemble -the structure of the input data and can directly be used to generate -arbitrarily-formatted output. - -A simple EBNF grammar snippet: - - group ::= '(' expression ')' - factor ::= integer | group - term ::= factor (('*' factor) | ('/' factor))* - expression ::= term (('+' term) | ('-' term))* - -is approximated using facilities of Spirit's /X3/ as seen in this code snippet: - - group = '(' >> expression >> ')'; - factor = integer | group; - term = factor >> *(('*' >> factor) | ('/' >> factor)); - expression = term >> *(('+' >> term) | ('-' >> term)); - -Through the magic of expression templates, this is perfectly valid and -executable C++ code. The production rule `expression` is, in fact, an object -that has a member function `parse` that does the work given a source code -written in the grammar that we have just declared. Yes, it's a calculator. We -shall simplify for now by skipping the type declarations and the definition of -the rule `integer` invoked by `factor`. Now, the production rule `expression` in -our grammar specification, traditionally called the `start` symbol, can -recognize inputs such as: - - 12345 - -12345 - +12345 - 1 + 2 - 1 * 2 - 1/2 + 3/4 - 1 + 2 + 3 + 4 - 1 * 2 * 3 * 4 - (1 + 2) * (3 + 4) - (-1 + 2) * (3 + -4) - 1 + ((6 * 200) - 20) / 6 - (1 + (2 + (3 + (4 + 5)))) - -Certainly we have modified the original EBNF syntax. This is done to -conform to C++ syntax rules. Most notably we see the abundance of shift >> -operators. Since there are no juxtaposition operators in C++, it is simply not -possible to write something like: - - a b - -as seen in math syntax, for example, to mean multiplication or, in our case, -as seen in EBNF syntax to mean sequencing (b should follow a). __x3__ -uses the shift `>>` operator instead for this purpose. We take the `>>` -operator, with arrows pointing to the right, to mean "is followed by". Thus we -write: - - a >> b - -The alternative operator `|` and the parentheses `()` remain as is. The -assignment operator `=` is used in place of EBNF's `::=`. Last but not least, -the Kleene star `*`, which in this case is a postfix operator in EBNF becomes a -prefix. Instead of: - - a* //... in EBNF syntax, - -we write: - - *a //... in Spirit. - -since there are no postfix stars, `*`, in C/C++. Finally, we terminate each -rule with the ubiquitous semi-colon, `;`. - -[endsect] diff --git a/doc/x3/preface.qbk b/doc/x3/preface.qbk deleted file mode 100644 index a6c2bd53a..000000000 --- a/doc/x3/preface.qbk +++ /dev/null @@ -1,75 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Preface] - -[:['["Examples of designs that meet most of the criteria for -"goodness" (easy to understand, flexible, efficient) are a -recursive-descent parser, which is traditional procedural -code. Another example is the STL, which is a generic library of -containers and algorithms depending crucially on both traditional -procedural code and on parametric polymorphism.]] [*--Bjarne -Stroustrup]] - -[heading How to use this manual] - -This document is roughly divided into 3 parts: - -# Tutorials: A step by step guide with heavily annotated code. These - are meant to get the user acquainted with the library as quickly as - possible. The objective is to build the confidence of the user in - using the library through abundant examples and detailed - instructions. Examples speak volumes and we have volumes of - examples! - -# Abstracts: A high level summary of key topics. The objective is to - give the user a high level view of the library, the key concepts, - background and theories. - -# Reference: Detailed formal technical reference. We start with a quick - reference -- an easy to use table that maps into the reference proper. - The reference proper starts with C++ concepts followed by - models of the concepts. - -Some icons are used to mark certain topics indicative of their relevance. -These icons precede some text to indicate: - -[table Icons - - [[Icon] [Name] [Meaning]] - - [[__note__] [Note] [Generally useful information (an aside that - doesn't fit in the flow of the text)]] - - [[__tip__] [Tip] [Suggestion on how to do something - (especially something that is not obvious)]] - - [[__important__] [Important] [Important note on something to take - particular notice of]] - - [[__caution__] [Caution] [Take special care with this - it may - not be what you expect and may cause bad - results]] - - [[__danger__] [Danger] [This is likely to cause serious - trouble if ignored]] -] - -This documentation is automatically generated by Boost QuickBook -documentation tool. QuickBook can be found in the __boost_tools__. - -[heading Support] - -Please direct all questions to Spirit's mailing list. You can subscribe -to the __spirit_list__. The mailing list has a searchable archive. A -search link to this archive is provided in __spirit__'s home page. You -may also read and post messages to the mailing list through -__spirit_general__ (thanks to __gmane__). The news group mirrors the -mailing list. Here is a link to the archives: __mlist_archive__. - -[endsect] [/ Preface] diff --git a/doc/x3/quick_reference.qbk b/doc/x3/quick_reference.qbk deleted file mode 100644 index 84fd70398..000000000 --- a/doc/x3/quick_reference.qbk +++ /dev/null @@ -1,372 +0,0 @@ -[/============================================================================== - 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) -===============================================================================/] - -This quick reference section is provided for convenience. You can use -this section as a sort of a "cheat-sheet" on the most commonly used X3 -components. It is not intended to be complete, but should give you an -easy way to recall a particular component without having to dig up on -pages and pages of reference documentation. - -[section Common Notation] - -[variablelist Notation - [[`P`] [Parser type]] - [[`p, a, b, c`] [Parser objects]] - [[`A, B, C`] [Attribute types of parsers `a`, `b` and `c`]] - [[`I`] [The iterator type used for parsing]] - [[`Unused`] [An `unused_type`]] - [[`Context`] [The enclosing rule's `Context` type]] - [[`attrib`] [An attribute value]] - [[`Attrib`] [An attribute type]] - [[`b`] [A boolean expression]] - [[`fp`] [A (lazy parser) function with signature `P(Unused, Context)`]] - [[`fa`] [A (semantic action) function with signature `void(Context&)`.]] - [[`first`] [An iterator pointing to the start of input]] - [[`last`] [An iterator pointing to the end of input]] - [[`Ch`] [Character-class specific character type (See __char_class_types__)]] - [[`ch`] [Character-class specific character (See __char_class_types__)]] - [[`ch2`] [Character-class specific character (See __char_class_types__)]] - [[`charset`] [Character-set specifier string (example: "a-z0-9")]] - [[`str`] [Character-class specific string (See __char_class_types__)]] - [[`Str`] [Attribute of `str`: `std::basic_string` where `T` is the underlying character type of `str`]] - [[`tuple<>`] [Used as a placeholder for a fusion sequence]] - [[`vector<>`] [Used as a placeholder for an STL container]] - [[`variant<>`] [Used as a placeholder for a boost::variant]] - [[`optional<>`] [Used as a placeholder for a boost::optional]] -] - -[endsect] -[section:char Character Parsers] - -[table - [[Expression] [Attribute] [Description]] - [[[x3_char `ch`]] [`Unused`] [Matches `ch`]] - [[[x3_char `lit(ch)`]] [`Unused`] [Matches `ch`]] - [[[x3_char `char_`]] [`Ch`] [Matches any character]] - [[[x3_char `char_(ch)`]] [`Ch`] [Matches `ch`]] - [[[x3_char `char_("c")`]] [`Ch`] [Matches a single char string literal, `c`]] - [[[x3_char `char_(ch, ch2)`]][`Ch`] [Matches a range of chars from `ch` to `ch2` (inclusive)]] - [[[x3_char `char_(charset)`]][`Ch`] [Matches a character set `charset`]] - - [[[x3_char_class `alnum`]] [`Ch`] [Matches a character based on the equivalent of - `std::isalnum` in the current character set]] - [[[x3_char_class `alpha`]] [`Ch`] [Matches a character based on the equivalent of - `std::isalpha` in the current character set]] - [[[x3_char_class `blank`]] [`Ch`] [Matches a character based on the equivalent of - `std::isblank` in the current character set]] - [[[x3_char_class `cntrl`]] [`Ch`] [Matches a character based on the equivalent of - `std::iscntrl` in the current character set]] - [[[x3_char_class `digit`]] [`Ch`] [Matches a character based on the equivalent of - `std::isdigit` in the current character set]] - [[[x3_char_class `graph`]] [`Ch`] [Matches a character based on the equivalent of - `std::isgraph` in the current character set]] - [[[x3_char_class `print`]] [`Ch`] [Matches a character based on the equivalent of - `std::isprint` in the current character set]] - [[[x3_char_class `punct`]] [`Ch`] [Matches a character based on the equivalent of - `std::ispunct` in the current character set]] - [[[x3_char_class `space`]] [`Ch`] [Matches a character based on the equivalent of - `std::isspace` in the current character set]] - [[[x3_char_class `xdigit`]] [`Ch`] [Matches a character based on the equivalent of - `std::isxdigit` in the current character set]] - [[[x3_char_class `lower`]] [`Ch`] [Matches a character based on the equivalent of - `std::islower` in the current character set]] - [[[x3_char_class `upper`]] [`Ch`] [Matches a character based on the equivalent of - `std::isupper` in the current character set]] -] - -[endsect] -[section:numeric Numeric Parsers] - -[table - [[Expression] [Attribute] [Description]] - [[[x3_real_number `float_`]] [`float`] [Parse a floating point number into a `float`]] - [[[x3_real_number `float_(num)`]] [`float`] [Parse a floating point number into a `float`, - a number is matched only if it's `num`]] - [[[x3_real_number `double_`]] [`double`] [Parse a floating point number into a `double`]] - [[[x3_real_number `double_(num)`]] [`double`] [Parse a floating point number into a `double`, - a number is matched only if it's `num`]] - [[[x3_real_number `long_double`]] [`long double`] [Parse a floating point number into a `long double`]] - [[[x3_real_number `long_double(num)`]] [`long double`] [Parse a floating point number into a `long double`, - a number is matched only if it's `num`]] - - [[[x3_unsigned_int `bin`]] [`unsigned`] [Parse a binary integer into an `unsigned`]] - [[[x3_unsigned_int `oct`]] [`unsigned`] [Parse an octal integer into an `unsigned`]] - [[[x3_unsigned_int `hex`]] [`unsigned`] [Parse a hexadecimal integer into an `unsigned`]] - [[[x3_unsigned_int `ushort_`]] [`unsigned short`] [Parse an unsigned short integer]] - [[[x3_unsigned_int `ushort_(num)`]] [`unsigned short`] [Parse an unsigned short integer, - a number is matched only if it's `num`]] - [[[x3_unsigned_int `ulong_`]] [`unsigned long`] [Parse an unsigned long integer]] - [[[x3_unsigned_int `ulong_(num)`]] [`unsigned long`] [Parse an unsigned long integer, - a number is matched only if it's `num`]] - [[[x3_unsigned_int `uint_`]] [`unsigned int`] [Parse an unsigned int]] - [[[x3_unsigned_int `uint_(num)`]] [`unsigned int`] [Parse an unsigned int, - a number is matched only if it's `num`]] - [[[x3_unsigned_int `ulong_long`]] [`unsigned long long`] [Parse an unsigned long long]] - [[[x3_unsigned_int `ulong_long(num)`]] [`unsigned long long`] [Parse an unsigned long long, - a number is matched only if it's `num`]] - [[[x3_signed_int `short_`]] [`short`] [Parse a short integer]] - [[[x3_signed_int `short_(num)`]] [`short`] [Parse a short integer, - a number is matched only if it's `num`]] - [[[x3_signed_int `long_`]] [`long`] [Parse a long integer]] - [[[x3_signed_int `long_(num)`]] [`long`] [Parse a long integer, - a number is matched only if it's `num`]] - [[[x3_signed_int `int_`]] [`int`] [Parse an int]] - [[[x3_signed_int `int_(num)`]] [`int`] [Parse an int, - a number is matched only if it's `num`]] - [[[x3_signed_int `long_long`]] [`long long`] [Parse a long long]] - [[[x3_signed_int `long_long(num)`]] [`long long`] [Parse a long long, - a number is matched only if it's `num`]] -] - -[endsect] -[section:string String Parsers] - -[table - [[Expression] [Attribute] [Description]] - [[[x3_lit_string `str`]] [`Unused`] [Matches `str`]] - [[[x3_lit_string `lit(str)`]] [`Unused`] [Matches `str`]] - [[[x3_lit_string `string(str)`]] [`Str`] [Matches `str`]] - - [[__x3_symbols__] [N/A] [Declare a symbol table, `sym`. `T` is the - data type associated with each key.]] - [[ -`` - sym.add - (str1, val1) - (str2, val2) - /*...more...*/ - ; -`` - ] - [N/A] [Add symbols into a symbol table, `sym`. - val1 and val2 are optional data of type `T`, - the data type associated with each key.]] - [[`sym`] [`T`] [Matches entries in the symbol table, `sym`. If - successful, returns the data associated with - the key]] -] - -[endsect] -[section:auxiliary Auxiliary Parsers] - -[table - [[Expression] [Attribute] [Description]] - [[__x3_eol__] [`Unused`] [Matches the end of line (`\r` or `\n` or `\r\n`)]] - [[__x3_eoi__] [`Unused`] [Matches the end of input (first == last)]] - [[__x3_eps__] [`Unused`] [Match an empty string]] - [[__x3_eps__`(b)`] [`Unused`] [If `b` is true, match an empty string]] - [[__x3_lazy__`(fp)`] [Attribute of `P` where `P` - is the return type of `fp`] [Invoke `fp` at parse time, returning a parser - `p` which is then called to parse.]] - [[`fp`] [see `lazy(fp)` above] [Equivalent to `lazy(fp)`]] - [[__x3_attr__] [`Attrib`] [Doesn't consume/parse any input, but exposes the - argument `attrib` as its attribute.]] -] - -[endsect] -[section:binary Binary Parsers] - -[table - [[Expression] [Attribute] [Description]] - [[[x3_native_binary `byte_`]] [8 bits native endian] [Matches an 8 bit binary in native endian representation]] - [[[x3_native_binary `word`]] [16 bits native endian] [Matches a 16 bit binary in native endian representation]] - [[[x3_big_binary `big_word`]] [16 bits big endian] [Matches a 16 bit binary in big endian representation]] - [[[x3_little_binary `little_word`]] [16 bits little endian][Matches a 16 bit binary in little endian representation]] - [[[x3_native_binary `dword`]] [32 bits native endian] [Matches a 32 bit binary in native endian representation]] - [[[x3_big_binary `big_dword`]] [32 bits big endian] [Matches a 32 bit binary in big endian representation]] - [[[x3_little_binary `little_dword`]] [32 bits little endian][Matches a 32 bit binary in little endian representation]] - [[[x3_native_binary `qword`]] [64 bits native endian] [Matches a 64 bit binary in native endian representation]] - [[[x3_big_binary `big_qword`]] [64 bits big endian] [Matches a 64 bit binary in big endian representation]] - [[[x3_little_binary `little_qword`]] [64 bits little endian][Matches a 64 bit binary in little endian representation]] -] - -[endsect] - -[section:directive Parser Directives] - -[table - [[Expression] [Attribute] [Description]] - [[__x3_lexeme__`[a]`] [`A`] [Disable skip parsing for `a`, does pre-skipping]] - [[[x3_no_skip `no_skip[a]`]] [`A`] [Disable skip parsing for `a`, no pre-skipping]] - [[__x3_no_case__`[a]`] [`A`] [Inhibits case-sensitivity for `a`]] - [[__x3_omit__`[a]`] [`Unused`] [Ignores the attribute type of `a`]] - [[__x3_matches__`[a]`] [`bool`] [Return if the embedded parser `a` matched its input]] - - [[__x3_raw__`[a]`] [__boost_iterator_range__``] [Presents the transduction of `a` as an iterator range]] - - [[__x3_expectd__`[a]`] [`A`] [Throw an exception if parsing `a` fails]] - - [[[x3_repeat `repeat[a]`]] [`vector`] [Repeat `a` zero or more times]] - [[[x3_repeat `repeat(N)[a]`]] [`vector`] [Repeat `a` `N` times]] - [[[x3_repeat `repeat(N, M)[a]`]] [`vector`] [Repeat `a` `N` to `M` times]] - [[[x3_repeat `repeat(N, inf)[a]`]] [`vector`] [Repeat `a` `N` or more times]] - - [[__x3_skip__`[a]`] [`A`] [Re-establish the skipper that got inhibited by lexeme or no_skip.]] - [[__x3_skip__`(p)[a]`] [`A`] [Use `p` as a skipper for parsing `a`]] -] - -[endsect] -[section:operator Parser Operators] - -[table - [[Expression] [Attribute] [Description]] - [[__x3_not_predicate__ `!a`] [`Unused`] [Not predicate. If the predicate `a` matches, - fail. Otherwise, return a zero length match.]] - [[__x3_and_predicate__ `&a`] [`Unused`] [And predicate. If the predicate `a` matches, - return a zero length match. Otherwise, fail.]] - [[__x3_optional__ `-a`] [`optional`] [Optional. Parse `a` zero or one time]] - [[__x3_kleene__ `*a`] [`vector`] [Kleene. Parse `a` zero or more times]] - [[__x3_plus__ `+a`] [`vector`] [Plus. Parse `a` one or more times]] - [[__x3_alternative__ `a | b`] [`variant`] [Alternative. Parse `a` or `b`]] - [[__x3_sequence__ `a >> b`] [`tuple`] [Sequence. Parse `a` followed by `b`]] - [[__x3_expect__ `a > b`] [`tuple`] [Expect. Parse `a` followed by `b`. `b` is - expected to match when `a` matches, otherwise, - an `expectation_failure` is thrown.]] - [[__x3_difference__ `a - b`] [`A`] [Difference. Parse `a` but not `b`]] - [[__x3_list__ `a % b`] [`vector`] [List. Parse `a` delimited `b` one or more times]] -] - -[endsect] -[section:action Parser Semantic Actions] - -[table - [[Expression] [Attribute] [Description]] - [[`p[fa]`] [Attribute of `p`] [Call semantic action, `fa` if p succeeds.]] -] - -[endsect] -[section Compound Attribute Rules] - -[heading Notation] - -The notation we will use will be of the form: - - a: A, b: B, ... --> composite-expression: composite-attribute - -`a`, `b`, etc. are the operands. `A`, `B`, etc. are the operand's -attribute types. `composite-expression` is the expression involving the -operands and `composite-attribute` is the resulting attribute type of -the composite expression. - -For instance: - - a: A, b: B --> (a >> b): tuple - -reads as: given, `a` and `b` are parsers, and `A` is the type of the -attribute of `a`, and `B` is the type of the attribute of `b`, then the -type of the attribute of `a >> b` will be `tuple`. - -[important In the attribute tables, we will use `vector` and -`tuple` as placeholders only. The notation of `vector` -stands for ['any __stl__ container] holding elements of type `A` and the -notation `tuple` stands for ['any __fusion__ sequence] holding -`A`, `B`, ... etc. elements. Finally, `Unused` stands for -__unused_type__. ] - -[heading Compound Parser Attribute Types] - -[table - [[Expression] [Attribute]] - - [[__x3_sequence__ (`a >> b`)] -[``a: A, b: B --> (a >> b): tuple -a: A, b: Unused --> (a >> b): A -a: Unused, b: B --> (a >> b): B -a: Unused, b: Unused --> (a >> b): Unused - -a: A, b: A --> (a >> b): vector -a: vector, b: A --> (a >> b): vector -a: A, b: vector --> (a >> b): vector -a: vector, b: vector --> (a >> b): vector``]] - - [[__x3_expect__ (`a > b`)] -[``a: A, b: B --> (a > b): tuple -a: A, b: Unused --> (a > b): A -a: Unused, b: B --> (a > b): B -a: Unused, b: Unused --> (a > b): Unused - -a: A, b: A --> (a > b): vector -a: vector, b: A --> (a > b): vector -a: A, b: vector --> (a > b): vector -a: vector, b: vector --> (a > b): vector``]] - - [[__x3_alternative__ (`a | b`)] -[``a: A, b: B --> (a | b): variant -a: A, b: Unused --> (a | b): optional -a: A, b: B, c: Unused --> (a | b | c): optional > -a: Unused, b: B --> (a | b): optional -a: Unused, b: Unused --> (a | b): Unused -a: A, b: A --> (a | b): A``]] - - [[__x3_difference__ (`a - b`)] -[``a: A, b: B --> (a - b): A -a: Unused, b: B --> (a - b): Unused``]] - - [[__x3_kleene__ (`*a`)] -[``a: A --> *a: vector -a: Unused --> *a: Unused``]] - [[__x3_plus__ (`+a`)] -[``a: A --> +a: vector -a: Unused --> +a: Unused``]] - - [[__x3_list__ (`a % b`)] -[``a: A, b: B --> (a % b): vector -a: Unused, b: B --> (a % b): Unused``]] - - [[[/ $$$ FIXME $$$ link spirit.x3.reference.directive.repeat] `repeat(...,...)[a]`] -[``a: A --> repeat(...,...)[a]: vector -a: Unused --> repeat(...,...)[a]: Unused``]] - - [[__x3_optional__ (`-a`)] -[``a: A --> -a: optional -a: Unused --> -a: Unused``]] - - [[`&a`] [`a: A --> &a: Unused`]] - [[`!b`] [`a: A --> !a: Unused`]] - -] - -[endsect] - -[section:non_terminals Nonterminals] - -[variablelist Notation - [[`Attr`] [Synthesized attribute. The rule return type.]] - [[`ID`] [The rule ID]] - [[`r, r2`] [Rules]] - [[`r_def, r2_def`] [A rule definition. By convention a rule named `r` should - have corresponding rule definition named `r_def`]] - [[`p`] [A parser expression]] -] - -[table - [[Expression] [Description]] - [[`rule const r = name;`] [Rule declaration. `ID` is required. - `Attr` is optional and defaults to __unused_type__. - `name` is an optional string that gives the rule - its name, useful for debugging and error handling.]] - [[`r.name()`] [Getting the name of a rule]] - [[`auto const r_def = p;`] [Rule definition]] - [[`BOOST_SPIRIT_DEFINE(r, r2, ...)`] [Links one or more rules (`r, r2, ...`) with - their definitions (`r_def, r2_def, ...`)]] -] - -[endsect] -[section:semantic_actions Parser Semantic Actions] - -Has the form: - - p[f] - -where `f` is a function with the signatures: - - void f(Context&); - -[/ $$$ TODO $$$ Fix this link: For more detailed information about semantic actions see:] - -[endsect] diff --git a/doc/x3/spirit_x3.qbk b/doc/x3/spirit_x3.qbk deleted file mode 100644 index bce603e1e..000000000 --- a/doc/x3/spirit_x3.qbk +++ /dev/null @@ -1,248 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 Joel de Guzman - Copyright (C) 2001-2011 Hartmut Kaiser - Copyright (C) 2024 Nana Sakisaka - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -===============================================================================/] - -[article Spirit X3 - [quickbook 1.5] - [version 3.10] - [authors [de Guzman, Joel], [Kaiser, Hartmut]] - [copyright 2001-2018 Joel de Guzman, Hartmut Kaiser] - [/ purpose Parser Library] - [license - Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt or copy at - [@http://www.boost.org/LICENSE_1_0.txt]) - ] -] - -[/ Nov 29, 2021 ] - -[/============================================================================= - Some links and defines -=============================================================================/] - -[def __version__ V3.10] - -[/ external] - -[def __gmane__ [@http://www.gmane.org Gmane]] -[def __mlist_archive__ [@http://news.gmane.org/gmane.comp.parsers.spirit.general]] -[def __boost_tools__ [@http://www.boost.org/tools/index.html Boost Tools]] -[def __fusion__ [@boost:/libs/fusion/doc/html/index.html Boost.Fusion]] -[def __boost_variant__ [@http://www.boost.org/doc/html/variant.html Boost.Variant]] -[def __stl__ [@https://en.wikipedia.org/wiki/Standard_Template_Library STL]] -[def __fwditer__ [@http://en.cppreference.com/w/cpp/named_req/ForwardIterator `ForwardIterator`]] -[def __outputiter__ [@http://en.cppreference.com/w/cpp/named_req/OutputIterator `OutputIterator`]] -[def __concepts__ [@http://www.boost.org/community/generic_programming.html#concept concepts]] -[def __endianness__ [@http://en.wikipedia.org/wiki/Endianness endianness]] -[def __iomanip__ [@http://www.cppreference.com/wiki/io/io_flags#manipulators Manipulators]] -[def __boost_iterator_range__ [@boost:/libs/range/doc/html/range/reference/utilities/iterator_range.html `boost::iterator_range`]] - -[template trac[number]'''TRAC#'''[number]''''''] -[template gh[number]'''GH#'''[number]''''''] -[template gh_pr[number]'''GH#'''[number]''''''] - -[/ Some images ] - -[def __note__ [$./images/note.png]] -[def __tip__ [$./images/tip.png]] -[def __important__ [$./images/important.png]] -[def __caution__ [$./images/caution.png]] -[def __danger__ [$./images/alert.png]] - -[def __x3__ /Spirit.X3/] - -[def __sd_start_stop__ [$./images/start_stop.png]] -[def __sd_terminals__ [$./images/terminal.png]] -[def __sd_non_terminals__ [$./images/non-terminal.png]] -[def __sd_sequence__ [$./images/sequence.png]] -[def __sd_choice__ [$./images/alternative.png]] -[def __sd_optional__ [$./images/optional.png]] -[def __sd_plus__ [$./images/plus.png]] -[def __sd_kleene__ [$./images/kleene.png]] -[def __sd_predicate__ [$./images/predicate.png]] -[def __sd_and_predicate__ [$./images/and_predicate.png]] -[def __sd_not_predicate__ [$./images/not_predicate.png]] -[def __pascal_string__ [$./images/pascal_string.png]] - -[def __syntax_diagrams__ [link spirit.abstracts.syntax_diagrams Syntax Diagram]] -[def __peg__ [link spirit.abstracts.parsing_expression_grammar Parsing Expression Grammar]] -[def __ast__ Abstract Syntax Tree] [/$$$ TODO: link me $$$] - -[def __sec_x3_reference__ [/ link spirit_x3.reference] X3 Reference] -[def __sec_x3_primitive__ [/ link spirit_x3.quick_reference.x3_parsers] X3 Parsers] -[def __sec_x3_compound__ [/ link spirit_x3.quick_reference.compound_attribute_rules] Parser Compound Attribute Rules] - -[/ support] -[def __info__ `info`] [/ TODO Link Me] -[def __unused_type__ `unused_type`] [/$$$ TODO: link me $$$] -[def __unused__ `unused`] [/$$$ TODO: link me $$$] -[def __char_class_types__ Character Class Types] [/$$$ TODO: link me $$$] - -[/ quick-ref] -[def __x3_quickref__ [link spirit_x3.quick_reference X3 Quick Reference]] -[def __x3_comp_attr_notation__ [link spirit_x3.quick_reference.compound_attribute_rules.notation Compound Attribute Notation]] - -[/ concepts] -[def __parser_concept__ [/ link spirit_x3.reference.parser_concepts.parser] `Parser`] -[def __primitive_parser_concept__ [/ link spirit_x3.reference.parser_concepts.primitiveparser] `PrimitiveParser`] -[def __unary_parser_concept__ [/ link spirit_x3.reference.parser_concepts.unaryparser] `UnaryParser`] -[def __binary_parser_concept__ [/ link spirit_x3.reference.parser_concepts.binaryparser] `BinaryParser`] -[def __nary_parser_concept__ [/ link spirit_x3.reference.parser_concepts.naryparser] `NaryParser`] -[def __x3_nonterminal__ [/ link spirit_x3.reference.parser_concepts.nonterminal] `Nonterminal`] -[def __x3_nonterminal_attribute__ [/ link spirit_x3.reference.parser_concepts.nonterminal.attributes] `Attribute`] - -[/ basics] -[def __x3_lazy_argument__ [/ link spirit_x3.reference.basics.lazy_argument] Lazy Argument] -[def __x3_lazy_arguments__ [/ link spirit_x3.reference.basics.lazy_argument] Lazy Arguments] -[def __char_encoding_namespace__ [/ link spirit_x3.reference.basics.character_encoding_namespace] Character Encoding Namespace] -[def __x3_basics_examples__ [/ link spirit_x3.reference.basics.examples] Basics Examples] - -[/ string] -[template x3_lit_string[str] [[/ link spirit_x3.reference.string.string] str]] -[def __string__ [/ link spirit_x3.reference.basics.string] String] -[def __x3_symbols__ [/ link spirit_x3.reference.string.symbols] `symbols`] - -[/ action] -[def __x3_semantic_actions__ Semantic Actions] [/ TODO Link Me] - -[/ char] -[template x3_char[str] [/ link spirit_x3.reference.char.char] [str]] -[template x3_char_class[str] [/ link spirit_x3.reference.char.char_class] [str]] -[template x3_lit_char[char] [/ link spirit_x3.reference.char.char] [char]] - -[/ numerics] -[template x3_signed_int[str] [/ link spirit_x3.reference.numeric.int] [str]] -[template x3_unsigned_int[str] [/ link spirit_x3.reference.numeric.uint] [str]] -[template x3_real_number[str] [/ link spirit_x3.reference.numeric.real] [str]] -[template x3_boolean[str] [/ link spirit_x3.reference.numeric.boolean] [str]] - -[/ binary] -[template x3_native_binary[str] [/ link spirit_x3.reference.binary.binary_native] [str]] -[template x3_little_binary[str] [/ link spirit_x3.reference.binary.binary_little] [str]] -[template x3_big_binary[str] [/ link spirit_x3.reference.binary.binary_big] [str]] - -[/ auxiliary] -[def __x3_attr__ [/ link spirit_x3.reference.auxiliary.attr] `attr(attrib)`] -[def __x3_eol__ [/ link spirit_x3.reference.auxiliary.eol] `eol`] -[def __x3_eoi__ [/ link spirit_x3.reference.auxiliary.eoi] `eoi`] -[def __x3_eps__ [/ link spirit_x3.reference.auxiliary.eps] `eps`] -[def __x3_lazy__ [/ link spirit_x3.reference.auxiliary.lazy] `lazy`] - -[/ directives] -[def __x3_lexeme__ [/ link spirit_x3.reference.directive.lexeme] `lexeme`] -[def __x3_no_case__ [/ link spirit_x3.reference.directive.no_case] `no_case`] -[def __x3_omit__ [/ link spirit_x3.reference.directive.omit] `omit`] -[def __x3_matches__ [/ link spirit_x3.reference.directive.matches] `matches`] -[def __x3_raw__ [/ link spirit_x3.reference.directive.raw] `raw`] -[def __x3_expectd__ [/ link spirit_x3.reference.directive.expect] `expect`] -[def __x3_repeat__ [/ link spirit_x3.reference.directive.repeat] `repeat`] -[template x3_repeat[str] [[/ link spirit_x3.reference.directive.repeat] str]] -[def __x3_skip__ [/ link spirit_x3.reference.directive.skip] `skip`] -[template x3_no_skip[str] [[/ link spirit_x3.reference.directive.no_skip] str]] -[def __x3_hold__ [/ link spirit_x3.reference.directive.hold] `hold`] - -[/ operator] -[def __x3_alternative__ [/ link spirit_x3.reference.operator.alternative] Alternative] -[def __x3_and_predicate__ [/ link spirit_x3.reference.operator.and_predicate] And Predicate] -[def __x3_difference__ [/ link spirit_x3.reference.operator.difference] Difference] -[def __x3_expect__ [/ link spirit_x3.reference.operator.expect] Expectation operator] -[def __x3_expectation_failure__ [/ link spirit_x3.reference.operator.expect.expectation_failure] `expectation_failure`] -[def __x3_kleene__ [/ link spirit_x3.reference.operator.kleene] Kleene] -[def __x3_list__ [/ link spirit_x3.reference.operator.list] List] -[def __x3_not_predicate__ [/ link spirit_x3.reference.operator.not_predicate] Not Predicate] -[def __x3_optional__ [/ link spirit_x3.reference.operator.optional] Optional] -[def __x3_plus__ [/ link spirit_x3.reference.operator.plus] Plus] -[def __x3_sequence__ [/ link spirit_x3.reference.operator.sequence] Sequence] - -[def __x3_stream__ [/ link spirit_x3.reference.stream.stream] `stream`] - -[/ nonterminal] -[def __x3_rule__ [/ link spirit_x3.reference.nonterminal.rule] rule] -[def __x3_rules__ [/ link spirit_x3.reference.nonterminal.rule] rules] -[def __x3_grammar__ [/ link spirit_x3.reference.nonterminal.grammar] grammar] -[def __x3_grammars__ [/ link spirit_x3.reference.nonterminal.grammar] grammars] - -[/ stream] -[template x3_match[str] [/ link spirit_x3.reference.parse_api.stream_api] str] -[template x3_auto[str] [/ link spirit_x3.reference.auto] str] -[def __create_parser__ [/ link spirit_x3.reference.parse_api.create_parser] `create_parser`] - -[def __parse_api__ [/ link spirit_x3.reference.parse_api] The Parse API] - -[/============================================================================= - Better Links (March 7, 2018) -=============================================================================/] - -[/ external ------------------------------------------------------------------] - -[def __boost__ [@http://www.boost.org/ Boost]] -[def __spirit__ [@http://boost-spirit.com Spirit]] -[def __spirit_list__ [@https://lists.sourceforge.net/lists/listinfo/spirit-general Spirit Mailing List]] -[def __spirit_general__ [@news://news.gmane.org/gmane.comp.spirit.general Spirit General NNTP news portal]] -[def __clang__ [@https://clang.llvm.org/ Clang]] -[def __rd__ [@https://en.wikipedia.org/wiki/Recursive_descent_parser Recursive Descent]] - -[/ Sections ------------------------------------------------------------------] - -[/ Tutorials -----------------------------------------------------------------] - -[template tutorial_roman[str] [link spirit_x3.tutorials.roman [str]]] -[template tutorial_employee[str] [link spirit_x3.tutorials.employee [str]]] -[template tutorial_annotation[str] [link spirit_x3.tutorials.annotation [str]]] -[template tutorial_error_handling[str] [link spirit_x3.tutorials.error_handling [str]]] -[template tutorial_minimal[str] [link spirit_x3.tutorials.minimal [str]]] - -[/ support -------------------------------------------------------------------] - -[def __x3_error_handler__ [/ link fix.me] error_handler] - -[/============================================================================= - Documentation Start -=============================================================================/] - -This is the documentation of the newest version of __spirit__ (currently, -__version__). - -*WARNING*: C++14 compilers support will be dropped soon. - -Spirit X3 in Boost 1.81 (scheduled to November 2022) will use C++17 features. - -Supported compilers will be: -* Clang 4 (currently 3.6) -* GCC 7 (currently 5) -* VS 2017 v15.8 (currently 2015 U3) - -[include preface.qbk] -[include introduction.qbk] -[include include.qbk]s -[include abstracts.qbk] - -[section Tutorials] -[include tutorial/tutorial_intro.qbk] -[include tutorial/warming_up.qbk] -[include tutorial/actions.qbk] -[include tutorial/complex.qbk] -[include tutorial/sum_tutorial.qbk] -[include tutorial/num_list2.qbk] -[include tutorial/num_list3.qbk] -[include tutorial/num_list4.qbk] -[include tutorial/roman.qbk] -[include tutorial/employee.qbk] -[include tutorial/minimal.qbk] -[include tutorial/annotation.qbk] -[include tutorial/rexpr.qbk] -[include tutorial/error_handling.qbk] -[include tutorial/non_throwing_expectations.qbk] -[endsect] - -[section Quick Reference] -[include quick_reference.qbk] -[endsect] - -[include changelog.qbk] diff --git a/doc/x3/tutorial/actions.qbk b/doc/x3/tutorial/actions.qbk deleted file mode 100644 index 1ef5c606d..000000000 --- a/doc/x3/tutorial/actions.qbk +++ /dev/null @@ -1,90 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section:semantic_actions Parser Semantic Actions] - -The example in the previous section was very simplistic. It only recognized -data, but did nothing with it. It answered the question: "Did the input match?". -Now, we want to extract information from what was parsed. For example, we would -want to store the parsed number after a successful match. To do this, you will -need ['semantic actions]. - -Semantic actions may be attached to any point in the grammar specification. -These actions are polymorphic function objects that are called whenever a part -of the parser successfully recognizes a portion of the input. Say you have a -parser `p`, and a polymorphic C++ function object `f`. You can make the parser -call `f` whenever it matches an input by attaching `f`: - - p[f] - -The expression above links `f` to the parser, `p`. `f` is expected to be a -polymorphic function object with the signature: - - template - void operator()(Context const& ctx) const; - -We can also use C++14 generic lambdas of the form: - - [](auto& ctx) { /*...*/ } - -From the context, we can extract relevant information: - -[table Parse Context Access Functions - [[Function] [Description] [Example]] - [[`_val`] [A reference to the attribute of the - innermost rule that directly or indirectly - invokes the parser `p`] [`_val(ctx) = "Gotya!"`]] - [[`_where`] [Iterator range to the input stream] [`_where(ctx).begin()`]] - [[`_attr`] [A reference to the attribute of the - parser `p`] [`_val(ctx) += _attr(ctx)`]] - [[`_pass`] [A reference to a `bool` flag that - can be used to force the `p` to fail] [`_pass(ctx) = false`]] -] - -[heading Examples of Semantic Actions] - -Given: - - struct print_action - { - template - void operator()(Context const& ctx) const - { - std::cout << _attr(ctx) << std::endl; - } - }; - -Take note that with function objects, we need to have an `operator()` with -the Context argument. If we don't care about the context, we can use -`unused_type`. We'll see more of `unused_type` elsewhere. `unused_type` is a -Spirit supplied support class. - -All examples parse inputs of the form: - - "{NNN}" - -Where NNN is an integer inside the curly braces (e.g. {44}). - -The first example shows how to attach a function object: - - parse(first, last, '{' >> int_[print_action()] >> '}'); - -What's new? Well `int_` is the sibling of `double_`. I'm sure you can guess -what this parser does. - -The next example shows how use C++14 lambda: - - auto f = [](auto& ctx){ std::cout << _attr(ctx) << std::endl; }; - parse(first, last, '{' >> int_[f] >> '}'); - -Attaching semantic actions is the first hurdle one has to tackle when getting -started with parsing with Spirit. Familiarize yourself with this task. - -The examples above can be found here: [@../../../example/x3/actions.cpp actions.cpp] - -[endsect] diff --git a/doc/x3/tutorial/annotation.qbk b/doc/x3/tutorial/annotation.qbk deleted file mode 100644 index a288c6651..000000000 --- a/doc/x3/tutorial/annotation.qbk +++ /dev/null @@ -1,417 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2018 Joel de Guzman - Copyright (C) 2025 Nana Sakisaka - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - - I would like to thank Rainbowverse, llc (https://primeorbial.com/) - for sponsoring this work and donating it to the community. -===============================================================================/] - -[section:annotation Annotations - Decorating the ASTs] - -As a prerequisite in understanding this tutorial, please review the previous -[tutorial_employee employee example]. This example builds on top of that -example. - -Stop and think about it... We're actually generating ASTs (abstract syntax -trees) in our previoius examples. We parsed a single structure and generated -an in-memory representation of it in the form of a struct: the struct -employee. If we changed the implementation to parse one or more employees, -the result would be a std::vector. We can go on and add more -hierarchy: teams, departments, corporations, etc. We can have an AST -representation of it all. - -This example shows how to annotate the AST with the iterator positions for -access to the source code when post processing using a client supplied -`on_success` handler. The example will show how to get the position in input -source stream that corresponds to a given element in the AST. - -In addition, This example also shows how to "inject" client data, using the -"with" directive, that the `on_success` handler can access as it is called -within the parse traversal through the parser's context. - -The full cpp file for this example can be found here: -[@../../../example/x3/annotation.cpp annotation.cpp] - -[heading The AST] - -First, we'll update our previous employee struct, this time separating the -person into its own struct. So now, we have two structs, the `person` and the -`employee`. Take note too that we now inherit `person` and `employee` from -`x3::position_tagged` which provides positional information that we can use -to tell the AST's position in the input stream anytime. - - namespace client { namespace ast - { - 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; - }; - }} - -Like before, we need to tell __fusion__ about our structs to make them -first-class fusion citizens that the grammar can utilize: - - BOOST_FUSION_ADAPT_STRUCT(client::ast::person, - first_name, last_name - ) - - BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, - age, who, salary - ) - -[heading x3::position_cache] - -Before we proceed, let me introduce a helper class called the -`position_cache`. It is a simple class that collects iterator ranges that -point to where each element in the AST are located in the input stream. Given -an AST, you can query the position_cache about AST's position. For example: - - auto pos = positions.position_of(my_ast); - -Where `my_ast` is the AST, `positions` and is the `position_cache`, -`position_of` returns an iterator range that points to the start and end -(`pos.begin()` and `pos.end()`) positions where the AST was parsed from. -`positions.begin()` and `positions.end()` points to the start and end of the -entire input stream. - -[heading on_success] - -The `on_success` gives you everything you want from semantic actions without -the visual clutter. Declarative code can and should be free from imperative -code. `on_success` as a concept and mechanism is an important departure from -how things are done in Spirit's previous version: Qi. - -As demonstrated in the previous [tutorial_employee employee example], the -preferred way to extract data from an input source is by having the parser -collect the data for us into C++ structs as it traverses the input stream. -Ideally, Spirit X3 grammars are fully attributed and declared in such a way -that you do not have to add any imperative code and there should be no need -for semantic actions at all. The parser simply works as declared and you get -your data back as a result. - -However, there are certain cases where there's no way to avoid introducing -imperative code. But semantic actions mess up our clean declarative grammars. -If we care to keep our code clean, `on_success` handlers are alternative -callback hooks to client code that are executed by the parser after a -successful parse without polluting the grammar. Like semantic actions, -`on_success` handlers have access to the AST, the iterators, and context. -But, unlike semantic actions, `on_success` handlers are cleanly separated -from the actual grammar. - -[*Note:] an `on_success` handler recieves a pre-skipped iterator even when -the rule definition disables pre-skipping via `no_skip` directive. - -[heading Annotation Handler] - -As discussed, we annotate the AST with its position in the input stream with -our `on_success` handler: - - // tag used to get the position cache from the context - struct position_cache_tag; - - struct annotate_position - { - template Se, typename T, typename Context> - void on_success( - It const& first, Se const& last, T& ast, Context const& context - ) const - { - auto& position_cache = x3::get(context).get(); - position_cache.annotate(ast, first, last); - } - }; - -`position_cache_tag` is a special tag we will use to get a reference to the -actual `position_cache`, client data that we will inject at very start, when -we call parse. More on that later. - -Our `on_success` handler gets a reference to the actual `position_cache` and -calls its `annotate` member function, passing in the AST and the iterators. -`position_cache.annotate(ast, first, last)` annotates the AST with -information required by `x3::position_tagged`. - -[heading The Parser] - -Now we'll write a parser for our employee. To simplify, inputs will be of the -form: - - { age, "forename", "surname", salary } - -[#__tutorial_annotated_employee_parser__] -Here we go: - - namespace 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 const quoted_string = "quoted_string"; - x3::rule const person = "person"; - x3::rule 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); - } - -[heading Rule Declarations] - - struct quoted_string_class; - struct person_class; - struct employee_class; - - x3::rule const quoted_string = "quoted_string"; - x3::rule const person = "person"; - x3::rule const employee = "employee"; - -Go back and review the original [link __tutorial_employee_parser__ employee parser]. -What has changed? - -* We split the single employee rule into three smaller rules: `quoted_string`, - `person` and `employee`. -* We're using forward declared rule classes: `quoted_string_class`, `person_class`, - and `employee_class`. - -[heading Rule Classes] - -Like before, in this example, the rule classes, `quoted_string_class`, -`person_class`, and `employee_class` provide statically known IDs for the -rules required by X3 to perform its tasks. In addition to that, the rule -class can also be extended to have some user-defined customization hooks that -are called: - -* On success: After a rule successfully parses an input. -* On Error: After a rule fails to parse. - -By subclassing the rule class from a client supplied handler such as our -`annotate_position` handler above: - - struct person_class : annotate_position {}; - struct employee_class : annotate_position {}; - -The code above tells X3 to check the rule class if it has an `on_success` or -`on_error` member functions and appropriately calls them on such events. - -[#__tutorial_with_directive__] -[heading The with Directive] - -For any parser `p`, one can inject supplementary data that semantic actions -and handlers can access later on when they are called. The general syntax is: - - with(data)[p] - -For our particular example, we use to inject the `position_cache` into the -parse for our `annotate_position` on_success handler to have access to: - - auto const parser = - // we pass our position_cache to the parser so we can access - // it later in our on_sucess handlers - with(std::ref(positions)) - [ - employees - ]; - -Typically this is done just before calling `x3::parse` or `x3::phrase_parse`. -`with` is a very lightwight operation. It is possible to inject as much data -as you want, even multiple `with` directives: - - with(data1) - [ - with(data2)[p] - ] - -Multiple `with` directives can (perhaps not obviously) be injected from -outside the called function. Here's an outline: - - template - void bar(Parser const& p) - { - // Inject data2 - auto const parser = with(data2)[p]; - x3::parse(first, last, parser); - } - - void foo() - { - // Inject data1 - auto const parser = with(data1)[my_parser]; - bar(p); - } - -[heading Let's Parse] - -Now we have the complete parse mechanism with support for annotations: - - using iterator_type = std::string::const_iterator; - using position_cache = boost::spirit::x3::position_cache>; - - std::vector - parse(std::string const& input, position_cache& positions) - { - using boost::spirit::x3::ascii::space; - - std::vector 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(std::ref(positions)) - [ - employees - ]; - - bool r = phrase_parse(iter, end, parser, space, ast); - - // ... Some error checking here - - return ast; - } - -Let's walk through the code. - -First, we have some typedefs for 1) The iterator type we are using for the -parser, `iterator_type` and 2) For the `position_cache` type. The latter is a -template that accepts the type of container it will hold. In this case, a -`std::vector`. - -The main parse function accepts an input, a std::string and a reference to a -position_cache, and returns an AST: `std::vector`. - -Inside the parse function, we first create an AST where parsed data will be -stored: - - std::vector ast; - -Then finally, we create a parser, injecting a reference to the `position_cache`, -and call phrase_parse: - - 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(std::ref(positions)) - [ - employees - ]; - - bool r = phrase_parse(iter, end, parser, space, ast); - -On successful parse, the AST, `ast`, will contain the actual parsed data. - -[heading Getting The Source Positions] - -Now that we have our main parse function, let's have an example sourcefile to -parse and show how we can obtain the position of an AST element, returned -after a successful parse. - -Given this 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 - } - )"; - -We call our parse function after instantiating a `position_cache` object that -will hold the source stream positions: - - position_cache positions{input.begin(), input.end()}; - auto ast = parse(input, positions); - -We now have an AST, `ast`, that contains the parsed results. Let us get the -source positions of the 2nd employee: - - auto pos = positions.position_of(ast[1]); // zero based of course! - -`pos` is an iterator range that contains iterators to the start and end of -`ast[1]` in the input stream. - -[heading Config] - -If you read the previous [tutorial_minimal Program Structure] tutorial where -we separated various logical modules of the parser into separate cpp and -header files, and you are wondering how to provide the context configuration -information (see [link tutorial_configuration Config Section]), we need to -supplement the context like this: - - using phrase_context_type = x3::phrase_parse_context::type; - - typedef x3::context< - position_cache_tag - , std::reference_wrapper - , phrase_context_type> - context_type; - -[endsect] diff --git a/doc/x3/tutorial/complex.qbk b/doc/x3/tutorial/complex.qbk deleted file mode 100644 index 684bd9ea8..000000000 --- a/doc/x3/tutorial/complex.qbk +++ /dev/null @@ -1,80 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Complex - Our first complex parser] - -Well, not really a complex parser, but a parser that parses complex numbers. - -Here's a simple parser expression for complex numbers: - - '(' >> double_ >> -(',' >> double_) >> ')' - | double_ - -What's new? Well, we have: - -# Alternates: e.g. `a | b`. Try `a` first. If it succeeds, good. If not, try the - next alternative, `b`. -# Optionals: e.g. -p. Match the parser p zero or one time. - -The complex parser presented above reads as: - -* One or two real numbers in parentheses, separated by comma (the second number is optional) -* *OR* a single real number. - -This parser can parse complex numbers of the form: - - (123.45, 987.65) - (123.45) - 123.45 - -Here goes, this time with actions: - - namespace client - { - template - bool parse_complex(Iterator first, Iterator last, std::complex& 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(rN, iN); - return r; - } - } - -The full cpp file for this example can be found here: -[@../../../example/x3/complex_number.cpp complex_number.cpp] - -The `double_` parser attaches this action: - - [&](auto& ctx){ n = _attr(ctx); } - -This assigns the parsed result (actually, the attribute of `double_`) to n. - -[endsect] diff --git a/doc/x3/tutorial/employee.qbk b/doc/x3/tutorial/employee.qbk deleted file mode 100644 index 34517dd1c..000000000 --- a/doc/x3/tutorial/employee.qbk +++ /dev/null @@ -1,223 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section:employee Employee - Parsing into structs] - -It's a common question in the __spirit_list__: How do I parse and place -the results into a C++ struct? Of course, at this point, you already -know various ways to do it, using semantic actions. There are many ways -to skin a cat. Spirit X3, being fully attributed, makes it even easier. -The next example demonstrates some features of Spirit X3 that make this -easy. In the process, you'll learn about: - -* More about attributes -* Auto rules -* Some more built-in parsers -* Directives - -First, let's create a struct representing an employee: - - namespace client { namespace ast - { - struct employee - { - int age; - std::string forename; - std::string surname; - double salary; - }; - }} - -Then, we need to tell __fusion__ about our employee struct to make it a first-class -fusion citizen that the grammar can utilize. If you don't know fusion yet, -it is a __boost__ library for working with heterogeneous collections of data, -commonly referred to as tuples. Spirit uses fusion extensively as part of its -infrastructure. - -In fusion's view, a struct is just a form of a tuple. You can adapt any struct -to be a fully conforming fusion tuple: - - BOOST_FUSION_ADAPT_STRUCT( - client::ast::employee, - age, forename, surname, salary - ) - -Now we'll write a parser for our employee. Inputs will be of the form: - - employee{ age, "forename", "surname", salary } - -[#__tutorial_employee_parser__] -Here goes: - - 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 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); - } - -The full cpp file for this example can be found here: -[@../../../example/x3/employee.cpp employee.cpp] - -Let's walk through this one step at a time (not necessarily from top to bottom). - -[heading Rule Declaration] - -We are assuming that you already know about rules. We introduced rules in the -previous [tutorial_roman Roman Numerals example]. Please go back and review -the previous tutorial if you have to. - - x3::rule employee = "employee"; - -[heading Lexeme] - - lexeme['"' >> +(char_ - '"') >> '"']; - -`lexeme` inhibits space skipping from the open brace to the closing brace. -The expression parses quoted strings. - - +(char_ - '"') - -parses one or more chars, except the double quote. It stops when it sees -a double quote. - -[heading Difference] - -The expression: - - a - b - -parses `a` but not `b`. Its attribute is just `A`; the attribute of `a`. `b`'s -attribute is ignored. Hence, the attribute of: - - char_ - '"' - -is just `char`. - -[heading Plus] - - +a - -is similar to Kleene star. Rather than match everything, `+a` matches one or more. -Like it's related function, the Kleene star, its attribute is a `std::vector` -where `A` is the attribute of `a`. So, putting all these together, the attribute -of - - +(char_ - '"') - -is then: - - std::vector - -[heading Sequence Attribute] - -Now what's the attribute of - - '"' >> +(char_ - '"') >> '"' - -? - -Well, typically, the attribute of: - - a >> b >> c - -is: - - fusion::vector - -where `A` is the attribute of `a`, `B` is the attribute of `b` and `C` is the -attribute of `c`. What is `fusion::vector`? - a tuple. - -[note If you don't know what I am talking about, see: [@http://tinyurl.com/6xun4j -Fusion Vector]. It might be a good idea to have a look into __fusion__ at this -point. You'll definitely see more of it in the coming pages.] - -[heading Attribute Collapsing] - -Some parsers, especially those very little literal parsers you see, like `'"'`, -do not have attributes. - -Nodes without attributes are disregarded. In a sequence, like above, all nodes -with no attributes are filtered out of the `fusion::vector`. So, since `'"'` has -no attribute, and `+(char_ - '"')` has a `std::vector` attribute, the -whole expression's attribute should have been: - - fusion::vector > - -But wait, there's one more collapsing rule: If the attribute is followed by a -single element `fusion::vector`, The element is stripped naked from its container. -To make a long story short, the attribute of the expression: - - '"' >> +(char_ - '"') >> '"' - -is: - - std::vector - -[heading Rule Definition] - -Again, we are assuming that you already know about rules and rule -definitions. We introduced rules in the previous [tutorial_roman Roman -Numerals example]. Please go back and review the previous tutorial if you -have to. - - employee = - lit("employee") - >> '{' - >> int_ >> ',' - >> quoted_string >> ',' - >> quoted_string >> ',' - >> double_ - >> '}' - ; - - BOOST_SPIRIT_DEFINE(employee); - -Applying our collapsing rules above, the RHS has an attribute of: - - fusion::vector - -These nodes do not have an attribute: - -* `lit("employee")` -* `'{'` -* `','` -* `'}'` - -[note In case you are wondering, `lit("employee")` is the same as "employee". We -had to wrap it inside `lit` because immediately after it is `>> '{'`. You can't -right-shift a `char[]` and a `char` - you know, C++ syntax rules.] - -Recall that the attribute of `parser::employee` is the `ast::employee` struct. - -Now everything is clear, right? The `struct employee` *IS* compatible with -`fusion::vector`. So, the RHS of `start` -uses start's attribute (a `struct employee`) in-situ when it does its work. - -[endsect] diff --git a/doc/x3/tutorial/error_handling.qbk b/doc/x3/tutorial/error_handling.qbk deleted file mode 100644 index 3d8db5501..000000000 --- a/doc/x3/tutorial/error_handling.qbk +++ /dev/null @@ -1,349 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2018 Joel de Guzman - Copyright (C) 2024-2025 Nana Sakisaka - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - - I would like to thank Rainbowverse, llc (https://primeorbial.com/) - for sponsoring this work and donating it to the community. -===============================================================================/] - -[section Error Handling] - -This tutorial wouldn't be complete without touching on error handling. As a -prerequisite in understanding this tutorial, please review the previous -[tutorial_employee employee] and [tutorial_annotation annotations] examples. -This example builds on top of these previous examples. - -The full cpp file for this example can be found here: -[@../../../example/x3/error_handling.cpp error_handling.cpp] - -Please review the previous [tutorial_annotation annotations example]. The -information there will be very helpful in understanding error handling. - -[heading The AST] - -Our AST is exactly the same as what we had before in the [tutorial_annotation -annotations]: - - namespace client { namespace ast - { - 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; - }; - }} - -We have two structs, the `person` and the `employee`. Each inherits from -`x3::position_tagged` which provides positional information that we can use -to tell the AST's position in the input stream anytime. We will need these -information for error handling and reporting. - -Like before, we need to tell __fusion__ about our structs to make them -first-class fusion citizens that the grammar can utilize: - - BOOST_FUSION_ADAPT_STRUCT(client::ast::person, - first_name, last_name - ) - - BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, - age, who, salary - ) - -[heading Expectations] - -There are occasions in which it is expected that the input must match a -particular parser or the input is invalid. Such cases generally arise after -matching a portion of a grammar, such that the context is fully known. In -such a situation, failure to match should result in an exception. For -example, when parsing an e-mail address, a name, an "@" and a domain name -must be matched or the address is invalid. - -Two X3 mechanisms facilitate parser expectations: - -# The expectation operator (__x3_expect__) -# The expect directive (__x3_expectd__`[p]`) - -The expectation operator (__x3_expect__) requires that the following parser -(`b`) match the input or an __x3_expectation_failure__ is emitted. Using a -client supplied `on_error` handler, the exception can be serviced by calling -the handler with the source iterators and context at which the parsing failed -can be reported. - -By contrast, the sequence operator (__x3_sequence__) does not require that -the following parser match the input, which allows for backtracking or simply -returning false from the parse function with no exceptions. - -The expect directive (__x3_expectd__`[p]`) requires that the argument parser -matches the input or an exception is emitted. Using on_error(), that -exception can be handled by calling a handler with the context at which the -parsing failed can be reported. - -[tip Check the [link spirit_x3.tutorials.non_throwing_expectations Non-throwing Expectations Tutorial] - for information on switching to more efficient error handling without using C++ exceptions. -] - -[heading on_error] - -`on_error` is the counterpart of `on_success`, as discussed in the -[tutorial_annotation annotations example]. While `on_success` handlers are -callback hooks to client code that are executed by the parser after a -/successful/ parse, `on_error` handlers are callback hooks to client code -that are executed by the parser when an __x3_expectation_failure__ is thrown -via the expect operator or directive. `on_error` handlers have access to the -iterators, the context and the exception that was thrown. - -[#__tutorial_error_handling__] -[heading Error Handling] - -Before we proceed, let me introduce a helper class, the -x3::__x3_error_handler__. It is utility class that provides __clang__ style -error reporting which gives you nice reports such as the following: - -[pre -In line 16: -Error! Expecting: person here: - 'I am not a person!' <--- this should be a person -____^_ -] - -We'll see later that this error message is exactly what this example emits. - -Here's our `on_error` handler: - - struct error_handler - { - template Se, typename Exception, typename Context> - [[nodiscard]] x3::error_handler_result - on_error( - It const& first, Se const& last, - Exception const& x, Context const& context - ) - { - auto& error_handler = x3::get(context).get(); - std::string message = "Error! Expecting: " + x3::which(x) + " here:"; - error_handler(x3::where(x), message); - return x3::error_handler_result::fail; - } - }; - -`x3::error_handler_tag` is a special tag we will use to get a reference to -the actual x3::__x3_error_handler__ that we will inject at very start, when -we call parse. We get the x3::__x3_error_handler__ here: - - auto& error_handler = x3::get(context).get(); - -The x3::__x3_error_handler__ handles all the nitty gritty details such as -determining the line number and actual column position, and formatting the -error message printed. All we have to do is provide the actual error string -which we extract from the __x3_expectation_failure__ exception: - - std::string message = "Error! Expecting: " + x3::which(x) + " here:"; - -Then, we return `x3::error_handler_result::fail` to tell X3 that we want to -fail the parse when such an event is caught. You can return one of: - -[table - [[`Action`] [Description]] - [[fail] [Quit and fail. Return a no_match.]] - [[retry] [Attempt error recovery, possibly moving the iterator position.]] - [[accept] [Force success, moving the iterator position appropriately.]] - [[rethrow] [Rethrows the error.]] -] - -[heading The Parser] - -Now we'll rewrite employee parser with error handling in mind. Like the -[tutorial_annotation annotations] example, inputs will be of the form: - - { age, "forename", "surname", salary } - -Here we go: - - namespace 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 const quoted_string = "quoted_string"; - x3::rule const person = "person"; - x3::rule 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 {}; - } - -Go back and review the [link __tutorial_annotated_employee_parser__ annotated -employee parser]. What has changed? It is almost identical, except: - -Where appropriate, we're using the expectation operator (__x3_expect__) in -place of the sequence operator (__x3_sequence__): - - auto const person_def = quoted_string > ',' > quoted_string; - - auto const employee_def = - '{' - > int_ > ',' - > person > ',' - > double_ - > '}' - ; - -You will have some "deterministic points" in the grammar. Those are the -places where backtracking *cannot* occur. For our example above, when you get -a `'{'`, you definitely must see an `int_` next. After that, you definitely -must have a `','` next and then a `person` and so on until the final `'}'`. -Otherwise, there is no point in proceeding and trying other branches, -regardless where they are. The input is definitely erroneous. When this -happens, an expectation_failure exception is thrown. Somewhere outward, the -error handler will catch the exception. In our case, it is caught in our -`on_error` handler. - -Notice too that we subclass the `employee_class` from our `error_handler`. By -doing so, we tell X3 that we want to call our `error_handler` whenever an -exception is thrown somewhere inside the `employee` rule and whatever else it -calls (i.e. the `person` and `quoted_string` rules). - -[heading Let's Parse] - -Now we have the complete parse mechanism with error handling: - - void parse(std::string const& input) - { - using boost::spirit::x3::ascii::space; - typedef std::string::const_iterator iterator_type; - - std::vector 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; - - // 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(std::ref(error_handler)) - [ - employees - ]; - - bool r = phrase_parse(iter, end, parser, space, ast); - - // ... Some final reports here - } - -Prior to calling `phrase_parse`, we first create an AST where parsed data will be -stored: - - std::vector ast; - -We also create the actual error handler, sending message to `std::cerr`: - - error_handler_type error_handler(iter, end, std::cerr); - -Then, we inject a reference to `error_handler`, using the `with` directive -similar to what we did in the [link __tutorial_with_directive__ annotations -example]: - - 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(std::ref(error_handler)) - [ - employees - ]; - -Now, if we give the parser an erroneous input: - - 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 - } - )"; - -The parser will complain as expected: - -[pre -------------------------- -Now we have some errors -In line 16: -Error! Expecting: person here: - 'I am not a person!' <--- this should be a person -____^_ -------------------------- -Parsing failed -------------------------- -] - -[endsect] diff --git a/doc/x3/tutorial/minimal.qbk b/doc/x3/tutorial/minimal.qbk deleted file mode 100644 index 7b01d1f31..000000000 --- a/doc/x3/tutorial/minimal.qbk +++ /dev/null @@ -1,240 +0,0 @@ -[/============================================================================== - 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) - - I would like to thank Rainbowverse, llc (https://primeorbial.com/) - for sponsoring this work and donating it to the community. -===============================================================================/] - -[section:minimal X3 Program Structure] - -As a prerequisite in understanding this tutorial, please review the previous -[tutorial_employee employee example]. This example builds on top of that -example. - -So far, to keep things simple, all of the tutorial programs are self -contained in one cpp file. In reality, you will want to separate various -logical modules of the parser into separate cpp and header files, decoupling -the interface from the implementation. - -There are many ways to structure an X3 parser, but the "minimal" example in -this tutorial shows the preferred way. This example basically reuses the same -parser as the [tutorial_employee employee example] for the sake of -familiarity, but structured to allow separate compilation of the actual -parser in its own definition file and cpp file. The cpp files, including main -see only the header files --the interfaces. This is a good example on how X3 -parsers are structured in a C++ application. - -[heading Structure] - -The program is structured in a directory with the following header and cpp -files: - -[table - [[`File` ] [Description ]] - [[[@../../../example/x3/minimal/ast.hpp ast.hpp]] [The AST ]] - [[[@../../../example/x3/minimal/ast_adapted.hpp ast_adapted.hpp]] [Fusion adapters ]] - [[[@../../../example/x3/minimal/config.hpp config.hpp]] [Configuration ]] - [[[@../../../example/x3/minimal/employee.hpp employee.hpp]] [Main parser API ]] - [[[@../../../example/x3/minimal/employee_def.hpp employee_def.hpp]] [Parser definitions ]] - [[[@../../../example/x3/minimal/employee.cpp employee.cpp]] [Parser instantiation ]] - [[[@../../../example/x3/minimal/main.cpp main.cpp]] [Main program ]] -] - -The contents of the files should already be familiar. It's essentially the -same [tutorial_employee employee example]. So I will skip the details on how -the parser works and focus only on the features needed for refactoring the -program into a modular structure suitable for real-world deployment. - -[heading AST] - -We place the AST declaration here: - - namespace client { namespace ast - { - struct employee - { - int age; - std::string forename; - std::string surname; - double salary; - }; - - using boost::fusion::operator<<; - }} - -[heading Fusion adapters] - -Here, we adapt the AST for Fusion, making it a first-class fusion citizen: - - BOOST_FUSION_ADAPT_STRUCT(client::ast::employee, - age, forename, surname, salary - ) - -[heading Main parser API] - -This is the main header file that all other cpp files need to include. - -[#__tutorial_spirit_declare__] -[heading BOOST_SPIRIT_DECLARE] - -Remember [link __tutorial_spirit_define__ `BOOST_SPIRIT_DEFINE`]? If not, -then you probably want to go back and review that section to get a better -understanding of what's happening. - -Here in the header file, instead of `BOOST_SPIRIT_DEFINE`, we use -`BOOST_SPIRIT_DECLARE` for the *top* rule. Behind the scenes, what's actually -happening is that we are declaring a `parse_rule` function in the client -namespace. - -If you went back and reviewed [link __tutorial_spirit_define__ -BOOST_SPIRIT_DEFINE], you'll see why it is exactly what we need to use for -header files. `BOOST_SPIRIT_DECLARE` generates function declarations that are -meant to be placed in hpp (header) files while `BOOST_SPIRIT_DEFINE` -generates function definitions that are meant to be placed in cpp files. - -[note `BOOST_SPIRIT_DECLARE` is variadic and may be used for one or more rules. -Example: `BOOST_SPIRIT_DECLARE(r1, r2, r3);`] - -In this example, the top rule is `employee`. We declare `employee` in this -header file: - - namespace client - { - namespace parser - { - namespace x3 = boost::spirit::x3; - using employee_type = x3::rule; - BOOST_SPIRIT_DECLARE(employee_type); - } - - parser::employee_type employee(); - } - -We also provide a function that returns an `employee` object. This is the -parser that we will use anywhere it is needed. X3 parser objects are very -lightweight. They are basically simple tags with no data other than the name -of the rule (e.g. "employee"). Notice that we are passing this by value. - -[heading Parser Definitions] - -Here is where we place the actual rules that make up our grammar: - - 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 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; - } - -In the parser definition, we use [link __tutorial_spirit_define__ -`BOOST_SPIRIT_DEFINE`] just like we did in the [tutorial_employee employee -example]. - -While this is another header file, it is not meant to be included by the -client. Its purpose is to be included by an instantiations cpp file (see -below). We place this in an `.hpp` file for flexibility, so we have the -freedom to instantiate the parser with different iterator types. - -[#tutorial_configuration] -[heading Configuration] - -Here, we declare some types for instantiating our X3 parser with. Remember -that Spirit parsers can work with any __fwditer__. We'll also need to provide -the initial context type. This is the context that X3 will use to initiate a -parse. For calling `phrase_parse`, you will need the `phrase_parse_context` -like we do below, passing in the skipper type. - - using iterator_type = std::string::const_iterator; - using context_type = x3::phrase_parse_context::type; - -For plain `parse`, we simply use `x3::unused_type`. - -[heading Parser Instantiation] - -Now we instantiate our parser here, for our specific configuration: - - namespace client { namespace parser - { - BOOST_SPIRIT_INSTANTIATE(employee_type, iterator_type, context_type); - }} - -For that, we use `BOOST_SPIRIT_INSTANTIATE`, passing in the parser type, -the iterator type, and the context type. - -[heading BOOST_SPIRIT_INSTANTIATE] - -Go back and review [link __tutorial_spirit_define__ `BOOST_SPIRIT_DEFINE`] -and [link __tutorial_spirit_declare__ `BOOST_SPIRIT_DECLARE`] to get a better -grasp of what's happening with `BOOST_SPIRIT_INSTANTIATE` and why it is -needed. - -So what the heck is `BOOST_SPIRIT_INSTANTIATE`? What we want is to isolate -the instantiation of our parsers (rules and all that), into separate -translation units (or cpp files, if you will). In this example, we want to -place our x3 employee stuff in [@../../../example/x3/minimal/employee.cpp -employee.cpp]. That way, we have separate compilation. Every time we update -our employee parser source code, we only have to build the `employee.cpp` -file. All the rest will not be affected. By compiling only once in one -translation unit, we save on build times and avoid code bloat. There is no -code duplication, which can happen otherwise if you simply include the -employee parser ([@../../../example/x3/minimal/employee.hpp employee.hpp]) -everywhere. - -But how do you do that. Remember that our parser definitions are also placed -in its own header file for flexibility, so we have the freedom to instantiate -the parser with different iterator types. - -What we need to do is explicitly instantiate the `parse_rule` function we -declared and defined via `BOOST_SPIRIT_DECLARE` and `BOOST_SPIRIT_DEFINE` -respectively, using `BOOST_SPIRIT_INSTANTIATE`. For our particular example, -`BOOST_SPIRIT_INSTANTIATE` expands to this code: - - template bool parse_rule( - employee_type rule_ - , iterator_type& first, iterator_type const& last - , context_type const& context, employee_type::attribute_type& attr); - -[heading Main Program] - -Finally, we have our main program. The code is the same as single cpp file -[tutorial_employee employee example], but here, we simply include three -header files: - - #include "ast.hpp" - #include "ast_adapted.hpp" - #include "employee.hpp" - -# `ast.hpp` for the AST declaration -# `ast_adapted.hpp` if you need to traverse the AST using fusion -# `employee.hpp` the main parser API - -[endsect] diff --git a/doc/x3/tutorial/non_throwing_expectations.qbk b/doc/x3/tutorial/non_throwing_expectations.qbk deleted file mode 100644 index 253c7e0e9..000000000 --- a/doc/x3/tutorial/non_throwing_expectations.qbk +++ /dev/null @@ -1,97 +0,0 @@ -[/============================================================================== - Copyright (C) 2024 Nana Sakisaka - - Distributed under the Boost Software License, Version 1.0. (See accompanying - file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -===============================================================================/] - -[section:non_throwing_expectations Non-throwing Expectations] - -By default, X3 throws __x3_expectation_failure__ when an expectation failure occurs. -While C++ exceptions are straightforward, they come with significant overhead -that can drastically impact your application's processing speed, especially if -your parser is called within a performance-critical loop. - -In short, even the simplest grammar, like the one below, would throw exceptions -100,000 times if invoked 100,000 times with mismatched input. - - x3::lit('a') > 'b' - -You can change this behavior to store the error in a user-provided variable -instead of throwing an exception. - -Non-throwing mode can be up to *1-90 times faster* than the traditional mode, -depending on the complexity of your grammar. - -[tip The performance improvement is capped by the overhead of C++ exceptions, - meaning the reduction in parse time is limited by the overhead that - exceptions would have introduced. -] - -[heading Migration Guide] - -To switch to non-throwing mode, define the macro `BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE` -as `0` before including X3 headers, and then make a few modifications to your -parser's entry point. - -Here's an example of a parser in its default (throwing) mode: - - #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 - } - } - -Next, adjust your code as follows to switch to non-throwing mode: - - #define BOOST_SPIRIT_X3_THROW_EXPECTATION_FAILURE 0 - #include - - void do_parse() - { - // ... setup your variables here... - - // convenient helper, defaults to `boost::optional>` - x3::expectation_failure_optional failure; - - bool const ok = x3::parse( - first, last, x3::with(failure)[parser]); - - if (!ok) - { - if (failure.has_value()) - { - // error handling - } - } - } - -[tip You can also inspect the variable within [link __tutorial_error_handling__ `on_error` handler]. -] - -That's it! All X3 parsers will behave semantically the same as before, -except that expectation failures will be stored in the variable instead of -being thrown as C++ exceptions. - -The following types are supported for the context value: - -* `bool` -* `std::optional>` -* `boost::optional>` -* `std::reference_wrapper` of optional types - -[endsect] diff --git a/doc/x3/tutorial/num_list2.qbk b/doc/x3/tutorial/num_list2.qbk deleted file mode 100644 index 20203399d..000000000 --- a/doc/x3/tutorial/num_list2.qbk +++ /dev/null @@ -1,49 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Number List - stuffing numbers into a std::vector] - -This sample demonstrates a parser for a comma separated list of numbers and -using a semantic action to collect the numbers into a `std::vector`. - - template - bool parse_numbers(Iterator first, Iterator last, std::vector& 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; - } - -The full cpp file for this example can be found here: -[@../../../example/x3/num_list/num_list2.cpp num_list2.cpp] - -This, again, is the same parser as before. This time, instead of summing up the -numbers, we stuff them in a `std::vector`. - - [&](auto& ctx){ v.push_back(_attr(ctx)); } - -[endsect] diff --git a/doc/x3/tutorial/num_list3.qbk b/doc/x3/tutorial/num_list3.qbk deleted file mode 100644 index 19e8455ae..000000000 --- a/doc/x3/tutorial/num_list3.qbk +++ /dev/null @@ -1,55 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Number List Redux - list syntax] - - -So far, we've been using the syntax: - - double_ >> *(',' >> double_) - -to parse a comma-delimited list of numbers. Such lists are common in parsing and -Spirit provides a simpler shortcut for them. The expression above can be -simplified to: - - double_ % ',' - -read as: a list of doubles separated by `','`. - -This sample, again a variation of our previous example, demonstrates just that: - - template - bool parse_numbers(Iterator first, Iterator last, std::vector& 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; - } - -The full cpp file for this example can be found here: -[@../../../example/x3/num_list/num_list3.cpp num_list3.cpp] - -[endsect] diff --git a/doc/x3/tutorial/num_list4.qbk b/doc/x3/tutorial/num_list4.qbk deleted file mode 100644 index ef20b130e..000000000 --- a/doc/x3/tutorial/num_list4.qbk +++ /dev/null @@ -1,71 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Number List Attribute - one more, with style] - -You've seen that the `double_` parser has a `double` attribute. All parsers have -an attribute, even complex parsers. Those that are composed from primitives -using operators, like the list parser, also have an attribute. It so happens that -the attribute of a list parser: - - p % d - -is a `std::vector` of the attribute of `p`. So, for our parser: - - - double_ % ',' - -we'll have an attribute of: - - std::vector - -So, what does this give us? Well, we can simply pass in a `std::vector` -to our number list parser and it will happily churn out our result in our -vector. For that to happen, we'll use a variation of the `phrase_parse` with -an additional argument: the parser's attribute. With the following arguments -passed to `phrase_parse` - -# An iterator pointing to the start of the input -# An iterator pointing to one past the end of the input -# The parser object -# Another parser called the skip parser -# The parser's attribute - -Our parser now is further simplified to: - - template - bool parse_numbers(Iterator first, Iterator last, std::vector& 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; - } - -The full cpp file for this example can be found here: -[@../../../example/x3/num_list/num_list4.cpp num_list4.cpp] - -[*Hey, no more actions!!!] Now we're entering the realm of attribute grammars. -Cool eh? - -[endsect] diff --git a/doc/x3/tutorial/rexpr.qbk b/doc/x3/tutorial/rexpr.qbk deleted file mode 100644 index 047def38b..000000000 --- a/doc/x3/tutorial/rexpr.qbk +++ /dev/null @@ -1,211 +0,0 @@ -[/============================================================================== - Copyright (C) 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) -===============================================================================/] - -[section:rexpr RExpressions - Recursive ASTs!] - -In this example, we'll explore more on how to create heierarchical ASTs. -We will parse a minimalistic JSON-like language and compile the results -into our data structures in the form of a tree. - -/rexpr/ is a parser for RExpressions, a language resembling a minimal subset -of json, limited to a dictionary (composed of key=value pairs) where the value -can itself be a string or a recursive dictionary. - -Here's an Example: - - { - "color" = "blue" - "size" = "29 cm." - "position" = { - "x" = "123" - "y" = "456" - } - } - -This simple parser for X3 is intended as a minimal starting point. It is -minimal, yet complete with all things necessary parts that make up rules (and -grammars), except error handling and reporting. - -The example can be found here: -[@../../../example/x3/rexpr/rexpr_min/rexpr.cpp rexpr.cpp] - -The same parser, but complete with error handling and reporting, better file -organization, separate compilation of grammars, and a full test harness, can -be found in this directory: - -[@../../../example/x3/rexpr/rexpr_full/ rexpr/rexpr_full/] - -[note rexpr_full is the canonical structure proposed as best practice on how -parsers are written using Spirit X3.] - -[heading The AST] - -Here's the AST: - - namespace client { namespace ast - { - namespace x3 = boost::spirit::x3; - - struct rexpr; - - struct rexpr_value : x3::variant< - std::string - , x3::forward_ast - > - { - using base_type::base_type; - using base_type::operator=; - }; - - typedef std::map rexpr_map; - typedef std::pair rexpr_key_value; - - struct rexpr - { - rexpr_map entries; - }; - }} - -`x3::variant` is a support utility in Spirit X3 that extends __boost_variant__. -Typically, you use __boost_variant__ right out of the box and refer to a -particular template instantiation using a typedef. For example: - - typedef boost::variant my_variant; - -Instead of doing that, we create a `class` (or `struct` in the case) that -subclasses from `x3::variant`. By making the variant a subclass, you have a -distinct type in your namespace. You also have control of the constructors -and assignment operators, as well as giving you the freedom to add more -functionality. - -`rexpr_value` has two variant elements. It can either be a `std::string` or a -`rexpr`. Since `rexpr` recursively contains a `rexpr_value`, it has to be -forward declared. This recursive data structure requires `rexpr` to be wrapped -in a `x3::forward_ast` as shown in the declaration. - -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 - ) - -So essentially, a `rexpr_value` value is either a `std::string` or a -`std::map`. - -[heading Walking the AST] - -We add a utility to print out the AST: - - 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; - }; - -Traversing the AST is a recursive exercise. `rexpr_printer` is a function -object and the main entry point is `void operator()(rexpr const& ast)`. Notice -how it recursively calls an instance of itself for each of the key value pairs, -using `boost::apply_visitor`. Before and after iterating through all the -elements in the map, the braces are printed to surround the entire body, taking -care of correct indentation at each point in the recursive traversal. - -The `operator()` for `std::string` should be self explanatory. It simply prints -the text inside double quotes. - -[heading The 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 - rexpr_value = "rexpr_value"; - - x3::rule - rexpr = "rexpr"; - - x3::rule - 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); - }} - -We declare three rules `rexpr_value`, `rexpr` and `rexpr_key_value`. Same deal -as before. The attributes declared for each rule are the same structures we -declared in our AST above. These are the structures our rules will produce. - -So, going top-down (from the start rule), `rexpr` is defined as zero or more -`rexpr_key_value`s enclosed inside the curly braces. That's the kleene star in -action there: `*rexpr_key_value`. - -[note Take note of the convention: we use `rexpr` name as the rule name and -`rexpr_def` as the rule definition name.] - -To make the grammar clean, we capture the `quoted_string` production using -C++ `auto`. - -`rexpr_value` is a `quoted_string` followed by the assignment operator `'='`, -followed by a `rexpr_value`. `rexpr_value` is a `quoted_string` /OR/ a `rexpr`. -This uses the alternative operator `|`, and maps nicely to the variant AST the -rule is associated with. - -Finally, we associate the rules and their definitions: - - BOOST_SPIRIT_DEFINE(rexpr_value, rexpr, rexpr_key_value); - -[endsect] diff --git a/doc/x3/tutorial/roman.qbk b/doc/x3/tutorial/roman.qbk deleted file mode 100644 index da6b50376..000000000 --- a/doc/x3/tutorial/roman.qbk +++ /dev/null @@ -1,264 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section:roman Roman Numerals] - -This example demonstrates: - -* The Symbol Table -* Non-terminal rules - -[heading Symbol Table] - -The symbol table holds a dictionary of symbols where each symbol is a sequence -of characters. The template class, can work efficiently with 8, 16, 32 and even -64 bit characters. Mutable data of type T are associated with each symbol. - -Traditionally, symbol table management is maintained separately outside the BNF -grammar through semantic actions. Contrary to standard practice, the Spirit -symbol table class `symbols` is a parser. An object of which may be used -anywhere in the EBNF grammar specification. It is an example of a dynamic -parser. A dynamic parser is characterized by its ability to modify its behavior -at run time. Initially, an empty symbols object matches nothing. At any time, -symbols may be added or removed, thus, dynamically altering its behavior. - -Each entry in a symbol table may have an associated mutable data slot. In this -regard, one can view the symbol table as an associative container (or map) of -key-value pairs where the keys are strings. - -The symbols class expects one template parameter to specify the data type -associated with each symbol: its attribute. There are a couple of -namespaces in X3 where you can find various versions of the symbols class -for handling different character encoding including ascii, standard, -standard_wide, iso8859_1, and unicode. The default symbol parser type in -the main x3 namespace is standard. - -Here's a parser for roman hundreds (100..900) using the symbol table. Keep in -mind that the data associated with each slot is the parser's attribute (which is -passed to attached semantic actions). - - struct hundreds_ : x3::symbols - { - hundreds_() - { - add - ("C" , 100) - ("CC" , 200) - ("CCC" , 300) - ("CD" , 400) - ("D" , 500) - ("DC" , 600) - ("DCC" , 700) - ("DCCC" , 800) - ("CM" , 900) - ; - } - - } hundreds; - -Here's a parser for roman tens (10..90): - - struct tens_ : x3::symbols - { - tens_() - { - add - ("X" , 10) - ("XX" , 20) - ("XXX" , 30) - ("XL" , 40) - ("L" , 50) - ("LX" , 60) - ("LXX" , 70) - ("LXXX" , 80) - ("XC" , 90) - ; - } - - } tens; - -and, finally, for ones (1..9): - - struct ones_ : x3::symbols - { - ones_() - { - add - ("I" , 1) - ("II" , 2) - ("III" , 3) - ("IV" , 4) - ("V" , 5) - ("VI" , 6) - ("VII" , 7) - ("VIII" , 8) - ("IX" , 9) - ; - } - - } ones; - -Now we can use `hundreds`, `tens` and `ones` anywhere in our parser expressions. -They are all parsers. - -[heading Rules] - -Up until now, we've been inlining our parser expressions, passing them directly -to the `phrase_parse` function. The expression evaluates into a temporary, -unnamed parser which is passed into the `phrase_parse` function, used, and then -destroyed. This is fine for small parsers. When the expressions get complicated, -you'd want to break the expressions into smaller easier-to-understand pieces, -name them, and refer to them from other parser expressions by name. - -A parser expression can be assigned to what is called a "rule". There are -various ways to declare rules. The simplest form is: - - rule const r = "some-name"; - -[heading Rule ID] - -At the very least, the rule needs an identification tag. This ID can be any -struct or class type and need not be defined. Forward declaration would suffice. -In subsequent tutorials, we will see that the rule ID can have additional -functionalities for error handling and annotation. - -[heading Rule Name] - -The name is optional, but is useful for debugging and error handling, as -we'll see later. Notice that rule `r` is declared `const`. Rules are -immutable and are best declared as `const`. Rules are lightweight and can be -passed around by value. Its only member variable is a `std::string`: its -name. - -[note Unlike Qi (Spirit V2), X3 rules can be used with both `phrase_parse` and -`parse` without having to specify the skip parser] - -[heading Rule Attributes] - -For our next example, there's one more rule form you should know about: - - rule const r = "some-name"; - -The Attribute parameter specifies the attribute type of the rule. You've seen -that our parsers can have an attribute. Recall that the `double_` parser has -an attribute of `double`. To be precise, these are /synthesized/ attributes. -The parser "synthesizes" the attribute value. If the parser is a function, -think of them as function return values. - -[heading Rule Definition] - -After having declared a rule, you need a definition for the rule. Example: - - auto const r_def = double_ >> *(',' >> double_); - -By convention, rule definitions have a _def suffix. Like rules, rule definitions -are immutable and are best declared as `const`. - -[#__tutorial_spirit_define__] -[heading BOOST_SPIRIT_DEFINE] - -Now that we have a rule and its definition, we tie the rule with a rule -definition using the `BOOST_SPIRIT_DEFINE` macro: - - BOOST_SPIRIT_DEFINE(r); - -Behind the scenes, what's actually happening is that we are defining a `parse_rule` -function in the client namespace that tells X3 how to invoke the rule. -And so for each rule defined using `BOOST_SPIRIT_DEFINE`, there is an -overloaded `parse_rule` function. At parse time, Spirit X3 recursively calls -the appropriate `parse_rule` function. - -[note `BOOST_SPIRIT_DEFINE` is variadic and may be used for one or more rules. -Example: `BOOST_SPIRIT_DEFINE(r1, r2, r3);`] - -[heading Grammars] - -Unlike Qi (Spirit V2), X3 discards the notion of a grammar as a concrete -entity for encapsulating rules. In X3, a grammar is simply a logical group of -rules that work together, typically with a single top-level start rule which -serves as the main entry point. X3 grammars are grouped using namespaces. -The roman numeral grammar is a very nice and simple example of a grammar: - - 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 const roman = "roman"; - - auto const roman_def = - eps [set_zero] - >> - ( - -(+lit('M') [add1000]) - >> -hundreds [add] - >> -tens [add] - >> -ones [add] - ) - ; - - BOOST_SPIRIT_DEFINE(roman); - } - -Things to take notice of: - -* The start rule's attribute is `unsigned`. - -* `_val(ctx)` gets a reference to the rule's synthesized attribute. - -* `_attr(ctx)` gets a reference to the parser's synthesized attribute. - -* `eps` is a special spirit parser that consumes no input but is always - successful. We use it to initialize the rule's synthesized - attribute, to zero before anything else. The actual parser starts at - `+lit('M')`, parsing roman thousands. Using `eps` this way is good - for doing pre and post initializations. - -* The rule `roman` and the definition `roman_def` are const objects. - -* The rule's ID is `class roman`. C++ allows you to declare the class - in the actual template declaration as you can see in the example: - - x3::rule const roman = "roman"; - -[heading Let's Parse!] - - 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"; - } - -`roman` is our roman numeral parser. This time around we are using the -no-skipping version of the parse functions. We do not want to skip any spaces! -We are also passing in an attribute, `unsigned result`, which will receive the -parsed value. - -The full cpp file for this example can be found here: -[@../../../example/x3/roman.cpp roman.cpp] - -[endsect] diff --git a/doc/x3/tutorial/sum_tutorial.qbk b/doc/x3/tutorial/sum_tutorial.qbk deleted file mode 100644 index 17a2bd190..000000000 --- a/doc/x3/tutorial/sum_tutorial.qbk +++ /dev/null @@ -1,75 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Sum - adding numbers] - -Here's a parser that sums a comma-separated list of numbers. - -Ok we've glossed over some details in our previous examples. First, our -includes: - - #include - #include - #include - -Then some using directives: - - namespace x3 = boost::spirit::x3; - namespace ascii = boost::spirit::x3::ascii; - - using x3::double_; - using ascii::space; - using x3::_attr; - -Now the actual parser: - - template - 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; - } - -The full cpp file for this example can be found here: -[@../../../example/x3/sum.cpp sum.cpp] - -This is almost like our original numbers list example. We're incrementally -building on top of our examples. This time though, like in the complex number -example, we'll be adding the smarts. There's an accumulator (`double& n`) that -adds the numbers parsed. On a successful parse, this number is the sum of all -the parsed numbers. - -The first `double_` parser attaches this action: - - [&](auto& ctx){ n = _attr(ctx); } - -This assigns the parsed result (actually, the attribute of `double_`) to `n`. -The second `double_` parser attaches this action: - - [&](auto& ctx){ n += _attr(ctx); } - -So, subsequent numbers add into `n`. - -That wasn't too bad, was it :-) ? - -[endsect] diff --git a/doc/x3/tutorial/tutorial_intro.qbk b/doc/x3/tutorial/tutorial_intro.qbk deleted file mode 100644 index 08edbabc9..000000000 --- a/doc/x3/tutorial/tutorial_intro.qbk +++ /dev/null @@ -1,42 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Quick Start] - -[heading Why would you want to use __x3__?] - -__x3__ is designed to be a practical parsing tool. The ability to generate a -fully-working parser from a formal EBNF specification inlined in C++ -significantly reduces development time. Programmers typically approach parsing -using ad hoc hacks with primitive tools such as scanf. Even regular-expression -libraries (such as boost regex) or scanners (such as Boost tokenizer) do not -scale well when we need to write more elaborate parsers. Attempting to write -even a moderately-complex parser using these tools leads to code that is hard to -understand and maintain. - -One prime objective is to make the tool easy to use. When one thinks of a -parser generator, the usual reaction is "it must be big and complex with a -steep learning curve." Not so. Spirit is designed to be fully scalable. The -library is structured in layers. This permits learning on an as-needed basis, -after only learning the minimal core and basic concepts. - -For development simplicity and ease in deployment, the entire library -consists of only header files, with no libraries to link against or build. -Just put the Spirit distribution in your include path, compile and run. Code -size? -very tight -essentially comparable to hand written recursive descent -code. - -Our tutorials will walk you through the simplest Spirit examples, incrementally -building on top of the earlier examples as we expose more and more features and -techniques. We will try to be as gentle as possible with the learning curve. -We will present the tutorials in a cookbook style approach. This style of -presentation is based on our BoostCon '07 and BoostCon '08 slides. - -Have fun! - -[endsect] [/ Quickstart] diff --git a/doc/x3/tutorial/warming_up.qbk b/doc/x3/tutorial/warming_up.qbk deleted file mode 100644 index 76f94cc65..000000000 --- a/doc/x3/tutorial/warming_up.qbk +++ /dev/null @@ -1,155 +0,0 @@ -[/============================================================================== - Copyright (C) 2001-2015 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) -===============================================================================/] - -[section Warming up] - -We'll start by showing examples of parser expressions to give you a feel on how -to build parsers from the simplest parser, building up as we go. When comparing -EBNF to __spirit__, the expressions may seem awkward at first. __spirit__ heavily -uses operator overloading to accomplish its magic. - -[heading Trivial Example #1 Parsing a number] - -Create a parser that will parse a floating-point number. - - double_ - -(You've got to admit, that's trivial!) The above code actually generates a -Spirit floating point parser (a built-in parser). Spirit has many pre-defined -parsers and consistent naming conventions help you keep from going insane! - -[heading Trivial Example #2 Parsing two numbers] - -Create a parser that will accept a line consisting of two floating-point numbers. - - double_ >> double_ - -Here you see the familiar floating-point numeric parser `double_` used twice, -once for each number. What's that `>>` operator doing in there? Well, they had -to be separated by something, and this was chosen as the "followed by" sequence -operator. The above program creates a parser from two simpler parsers, glueing -them together with the sequence operator. The result is a parser that is a -composition of smaller parsers. Whitespace between numbers can implicitly be -consumed depending on how the parser is invoked (see below). - -[note When we combine parsers, we end up with a "bigger" parser, but - it's still a parser. Parsers can get bigger and bigger, nesting more and more, - but whenever you glue two parsers together, you end up with one bigger parser. - This is an important concept. -] - -[heading Trivial Example #3 Parsing zero or more numbers] - -Create a parser that will accept zero or more floating-point numbers. - - *double_ - -This is like a regular-expression Kleene Star, though the syntax might look a -bit odd for a C++ programmer not used to seeing the `*` operator overloaded like -this. Actually, if you know regular expressions it may look odd too since the -star is before the expression it modifies. C'est la vie. Blame it on the fact -that we must work with the syntax rules of C++. - -Any expression that evaluates to a parser may be used with the Kleene Star. -Keep in mind that C++ operator precedence rules may require you to put -expressions in parentheses for complex expressions. The Kleene Star -is also known as a Kleene Closure, but we call it the Star in most places. - -[heading Trivial Example #4 Parsing a comma-delimited list of numbers] - -This example will create a parser that accepts a comma-delimited list of -numbers. - - double_ >> *(char_(',') >> double_) - -Notice `char_(',')`. It is a literal character parser that can recognize the -comma `','`. In this case, the Kleene Star is modifying a more complex parser, -namely, the one generated by the expression: - - (char_(',') >> double_) - -Note that this is a case where the parentheses are necessary. The Kleene star -encloses the complete expression above. - -[heading Let's Parse!] - -We're done with defining the parser. So the next step is now invoking this -parser to do its work. There are a couple of ways to do this. For now, we will -use the `phrase_parse` function. One overload of this function accepts four -arguments: - -# An iterator pointing to the start of the input -# An iterator pointing to one past the end of the input -# The parser object -# Another parser called the skip parser - -In our example, we wish to skip spaces and tabs. Another parser named `space` -is included in Spirit's repertoire of predefined parsers. It is a very simple -parser that simply recognizes whitespace. We will use `space` as our skip -parser. The skip parser is the one responsible for skipping characters in -between parser elements such as the `double_` and `char_`. - -Ok, so now let's parse! - - template - 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; - } -The parse function returns `true` or `false` depending on the result of -the parse. The first iterator is passed by reference. On a successful -parse, this iterator is repositioned to the rightmost position consumed -by the parser. If this becomes equal to `last`, then we have a full -match. If not, then we have a partial match. A partial match happens -when the parser is only able to parse a portion of the input. - -Note that we inlined the parser directly in the call to parse. Upon calling -parse, the expression evaluates into a temporary, unnamed parser which is passed -into the parse() function, used, and then destroyed. - -Here, we opted to make the parser generic by making it a template, parameterized -by the iterator type. By doing so, it can take in data coming from any STL -conforming sequence as long as the iterators conform to a forward iterator. - -You can find the full cpp file here: -[@../../../example/x3/num_list/num_list1.cpp num_list1.cpp] - -[note `char` and `wchar_t` operands - -The careful reader may notice that the parser expression has `','` instead of -`char_(',')` as the previous examples did. This is ok due to C++ syntax rules of -conversion. There are `>>` operators that are overloaded to accept a `char` or -`wchar_t` argument on its left or right (but not both). An operator may be -overloaded if at least one of its parameters is a user-defined type. In this -case, the `double_` is the 2nd argument to `operator>>`, and so the proper -overload of `>>` is used, converting `','` into a character literal parser. - -The problem with omitting the `char_` should be obvious: `'a' >> 'b'` is not a -spirit parser, it is a numeric expression, right-shifting the ASCII (or another -encoding) value of `'a'` by the ASCII value of `'b'`. However, both -`char_('a') >> 'b'` and `'a' >> char_('b')` are Spirit sequence parsers -for the letter `'a'` followed by `'b'`. You'll get used to it, sooner or later. -] - -Finally, take note that we test for a full match (i.e. the parser fully parsed -the input) by checking if the first iterator, after parsing, is equal to the end -iterator. You may strike out this part if partial matches are to be allowed. - -[endsect] [/ Warming up] diff --git a/meta/explicit-failures-markup.xml b/meta/explicit-failures-markup.xml deleted file mode 100644 index 2ff35f8fc..000000000 --- a/meta/explicit-failures-markup.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/meta/libraries.json b/meta/libraries.json deleted file mode 100644 index acbdeba8a..000000000 --- a/meta/libraries.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "key": "spirit_x4", - "name": "Spirit.X4", - "authors": [ - "Joel de Guzman", - "Hartmut Kaiser", - "Dan Nuffer" - ], - "description": "A modern, header-only PEG parser combinator library for C++23.", - "category": [ - "Container", - "Data", - "IO", - "Parsing", - "String" - ], - "maintainers": [ - "Nana Sakisaka ", - "Joel de Guzman " - ], - "cxxstd": "23" -} diff --git a/sublibs b/sublibs deleted file mode 100644 index 5a0617c57..000000000 --- a/sublibs +++ /dev/null @@ -1 +0,0 @@ -The existence of this file tells the regression reporting programs that the directory contains sub-directories which are libraries. \ No newline at end of file diff --git a/test/Jamfile b/test/Jamfile deleted file mode 100644 index 45dbf844c..000000000 --- a/test/Jamfile +++ /dev/null @@ -1,22 +0,0 @@ -#============================================================================== -# Copyright (c) 2001-2011 Joel de Guzman -# Copyright (c) 2001-2012 Hartmut Kaiser -# Copyright (c) 2011 Bryce Lelbach -# Copyright (c) 2025 Nana Sakisaka -# -# Use, modification and distribution is subject to the Boost Software -# License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) -#============================================================================== - -project - : requirements - /boost/spirit_x4//boost_spirit_x4 - BOOST_SPIRIT_CI_IS_B2 - CATCH_CONFIG_FAST_COMPILE - CATCH_CONFIG_NO_USE_BUILTIN_CONSTANT_P - DO_NOT_USE_WMAIN - ; - -build-project x4 ; - diff --git a/test/x4/Jamfile b/test/x4/Jamfile deleted file mode 100644 index 876fcbdc4..000000000 --- a/test/x4/Jamfile +++ /dev/null @@ -1,131 +0,0 @@ -#============================================================================== -# Copyright (c) 2001-2013 Joel de Guzman -# Copyright (c) 2001-2012 Hartmut Kaiser -# Copyright (c) 2011 Bryce Lelbach -# Copyright (c) 2025 Nana Sakisaka -# -# Distributed under the 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-search /boost/config/checks ; -import config : requires ; -import testing ; - -project spirit-x4 - : requirements - . - 512 - [ requires - # Assume all the cxx11 checks succeed if any of cxx14 does. - #cxx14_binary_literals # grep -Er "[0-9]+b[0-9]+" * - #cxx14_constexpr - cxx14_decltype_auto # grep -r "decltype(auto)" * - #cxx14_digit_separators # grep -Er "[0-9]+'[0-9]+" * - cxx14_generic_lambdas # grep -Er "]\s*\\([^\\)]*auto" * - #cxx14_hdr_shared_mutex # grep -r "shared_mutex" * - #cxx14_initialized_lambda_captures # grep -Er "\\[[^=\\]]+=" * - #cxx14_aggregate_nsdmi - cxx14_return_type_deduction # grep -Er "auto[^\\(=\\)]+\(" * - #cxx14_std_exchange # grep -r "exchange" * - cxx14_variable_templates - ] - ; - -local subproject-name = x4 ; - -rule run ( sources + : args * : input-files * - : requirements * : target-name ? : default-build * ) -{ - target-name ?= $(subproject-name)_$(sources[1]:D=:S=) ; - return [ testing.run $(sources) : $(args) : $(input-files) - : $(requirements) : $(target-name) : $(default-build) ] ; -} - -rule compile ( sources + : requirements * : target-name ? ) -{ - target-name ?= $(subproject-name)_$(sources[1]:D=:S=) ; - return [ testing.compile $(sources) - : $(requirements) : $(target-name) ] ; -} - -rule compile-fail ( sources + : requirements * : target-name ? ) -{ - target-name ?= $(subproject-name)_$(sources[1]:D=:S=) ; - return [ testing.compile-fail $(sources) - : $(requirements) : $(target-name) ] ; -} - -obj catch2 : catch_amalgamated.cpp ; - -run parser.cpp catch2 ; -run context.cpp catch2 ; -run attribute.cpp catch2 ; -run x3_rule_problem.cpp catch2 ; - -run actions.cpp catch2 ; -run alternative.cpp catch2 ; -run and_predicate.cpp catch2 ; -run attr.cpp catch2 ; -run bool.cpp catch2 ; -run char.cpp catch2 ; -run char_class.cpp catch2 ; -run container_support.cpp catch2 ; -run debug.cpp catch2 ; -run difference.cpp catch2 ; -run eoi.cpp catch2 ; -run eol.cpp catch2 ; -run eps.cpp catch2 ; - -run expect.cpp catch2 ; - -run extract_int.cpp catch2 ; -run int.cpp catch2 ; -run kleene.cpp catch2 ; -run lexeme.cpp catch2 ; -run lit.cpp catch2 ; -run list.cpp catch2 ; -run matches.cpp catch2 ; -run no_case.cpp catch2 ; -run no_skip.cpp catch2 ; -run not_predicate.cpp catch2 ; -run omit.cpp catch2 ; -run optional.cpp catch2 ; -run plus.cpp catch2 ; -run with.cpp catch2 ; -run with_local.cpp catch2 ; -run as.cpp catch2 ; - -run raw.cpp catch2 ; -run real1.cpp catch2 ; -run real2.cpp catch2 ; -run real3.cpp catch2 ; -run rule1.cpp catch2 ; -run rule2.cpp catch2 ; -run rule3.cpp catch2 ; -run rule4.cpp catch2 ; -run sequence.cpp catch2 ; -run skip.cpp catch2 ; -run symbols1.cpp catch2 ; -run symbols2.cpp catch2 ; -run symbols3.cpp catch2 ; -run tst.cpp catch2 ; - -run uint.cpp catch2 ; -run uint_radix.cpp catch2 ; - -run repeat.cpp catch2 ; -run seek.cpp catch2 ; - -run unused.cpp catch2 ; -run attribute_type_check.cpp catch2 ; -run error_handler.cpp catch2 ; -run iterator.cpp catch2 ; - -run to_utf8.cpp catch2 ; - -obj rule_separate_tu_grammar : rule_separate_tu_grammar.cpp ; -run rule_separate_tu.cpp rule_separate_tu_grammar catch2 ; - -obj grammar_linker : grammar.cpp ; -run grammar_linker.cpp grammar_linker catch2 ; From 9bdc987bc667f0d7f5ac1fef5790f8a1de459d60 Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:06:16 +0900 Subject: [PATCH 2/3] Fix the upstream Boost version tag used for dependency resolution --- .github/workflows/ci.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 870b41d3c..bb74fda17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -99,14 +99,6 @@ jobs: steps: - uses: actions/checkout@v5 - with: - # required for upstream Boost version detection - # sadly not working due to upstream bug: https://github.com/actions/checkout/issues/1471 - fetch-tags: true - - - name: Fetch git tags - run: | - git fetch --depth=1 origin +refs/tags/*:refs/tags/* - name: Initialize Ubuntu if: matrix.os.name == 'ubuntu' @@ -152,7 +144,7 @@ jobs: echo "COMPILER_FULL_VERSION=$COMPILER_FULL_VERSION" echo "compiler-full-version=$COMPILER_FULL_VERSION" >> "$GITHUB_OUTPUT" - export BOOST_RELEASE_VERSION_NAME=$(git for-each-ref refs/tags --sort=-refname --format='%(refname:lstrip=-1)' --count=1) + export BOOST_RELEASE_VERSION_NAME=boost-1.89.0 # Fixed on the timing of X4's fork echo "BOOST_RELEASE_VERSION_NAME: $BOOST_RELEASE_VERSION_NAME" echo "BOOST_RELEASE_VERSION_NAME=$BOOST_RELEASE_VERSION_NAME" >> "$GITHUB_OUTPUT" From aa92b4dc36505fe94fea8f29a26544db0dec9bc8 Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Tue, 3 Feb 2026 16:19:23 +0900 Subject: [PATCH 3/3] Fix workspace path during build --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb74fda17..139e0ff68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -262,7 +262,7 @@ jobs: shell: bash run: | set -xe - cp -rp "${{ github.workspace }}" libs/ + cp -rp "${{ github.workspace }}" libs/spirit_x4 cd libs/spirit_x4 cmake ${{ steps.deps-info.outputs.BOOST_SPIRIT_X4_CMAKE_ARGS }} -B build \ -DCMAKE_CXX_COMPILER=${{ matrix.compiler.executable }} \