diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64d20df71..139e0ff68 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 }}" @@ -100,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' @@ -153,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" @@ -271,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 }} \ 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 101b5f780..000000000 Binary files a/doc/x3/html/images/alert.png and /dev/null differ diff --git a/doc/x3/html/images/alternative.png b/doc/x3/html/images/alternative.png deleted file mode 100644 index f2ed74477..000000000 Binary files a/doc/x3/html/images/alternative.png and /dev/null differ diff --git a/doc/x3/html/images/and_predicate.png b/doc/x3/html/images/and_predicate.png deleted file mode 100644 index 761052cc9..000000000 Binary files a/doc/x3/html/images/and_predicate.png and /dev/null differ diff --git a/doc/x3/html/images/caution.png b/doc/x3/html/images/caution.png deleted file mode 100644 index 4be6d0723..000000000 Binary files a/doc/x3/html/images/caution.png and /dev/null differ diff --git a/doc/x3/html/images/important.png b/doc/x3/html/images/important.png deleted file mode 100644 index 994325ed7..000000000 Binary files a/doc/x3/html/images/important.png and /dev/null differ diff --git a/doc/x3/html/images/kleene.png b/doc/x3/html/images/kleene.png deleted file mode 100644 index 34c1ad452..000000000 Binary files a/doc/x3/html/images/kleene.png and /dev/null differ diff --git a/doc/x3/html/images/non-terminal.png b/doc/x3/html/images/non-terminal.png deleted file mode 100644 index 3ff530e2f..000000000 Binary files a/doc/x3/html/images/non-terminal.png and /dev/null differ diff --git a/doc/x3/html/images/not_predicate.png b/doc/x3/html/images/not_predicate.png deleted file mode 100644 index 0a0c0de9f..000000000 Binary files a/doc/x3/html/images/not_predicate.png and /dev/null differ diff --git a/doc/x3/html/images/note.png b/doc/x3/html/images/note.png deleted file mode 100644 index c425ecb30..000000000 Binary files a/doc/x3/html/images/note.png and /dev/null differ diff --git a/doc/x3/html/images/optional.png b/doc/x3/html/images/optional.png deleted file mode 100644 index 8a9d91307..000000000 Binary files a/doc/x3/html/images/optional.png and /dev/null differ diff --git a/doc/x3/html/images/pascal_string.png b/doc/x3/html/images/pascal_string.png deleted file mode 100644 index 119e9ccfa..000000000 Binary files a/doc/x3/html/images/pascal_string.png and /dev/null differ diff --git a/doc/x3/html/images/plus.png b/doc/x3/html/images/plus.png deleted file mode 100644 index f58a5b364..000000000 Binary files a/doc/x3/html/images/plus.png and /dev/null differ diff --git a/doc/x3/html/images/predicate.png b/doc/x3/html/images/predicate.png deleted file mode 100644 index 81740707f..000000000 Binary files a/doc/x3/html/images/predicate.png and /dev/null differ diff --git a/doc/x3/html/images/sequence.png b/doc/x3/html/images/sequence.png deleted file mode 100644 index 481519793..000000000 Binary files a/doc/x3/html/images/sequence.png and /dev/null differ diff --git a/doc/x3/html/images/start_stop.png b/doc/x3/html/images/start_stop.png deleted file mode 100644 index 8680f24c2..000000000 Binary files a/doc/x3/html/images/start_stop.png and /dev/null differ diff --git a/doc/x3/html/images/terminal.png b/doc/x3/html/images/terminal.png deleted file mode 100644 index f688adb18..000000000 Binary files a/doc/x3/html/images/terminal.png and /dev/null differ diff --git a/doc/x3/html/images/tip.png b/doc/x3/html/images/tip.png deleted file mode 100644 index f5e54323b..000000000 Binary files a/doc/x3/html/images/tip.png and /dev/null differ diff --git a/doc/x3/include.qbk b/doc/x3/include.qbk deleted file mode 100644 index f2d712faf..000000000 --- a/doc/x3/include.qbk +++ /dev/null @@ -1,29 +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 Include] - -Spirit is a header file only library. There are no libraries to link to. -To use Spirit X3 simply include: - - #include - -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 ;