I'm migrating a hand-written parser to Boost.Spirit (2.5.4). First impressions are positive, but since I'm using C++17, X3 seems like a very attractive option.
Fortunately, there are many resources available about X3:
However:
So I'm worried: is X3 a good bet? Not only of maintenance, but does it hold its promesses compared to its predecessor?
I did my homework badly, similar questions were asked elsewhere:
Spirit X3 is being used in production (the developers state this on the mailing list).
It's strictly still "beta": interfaces and implementation may be subject to change.
All in all, I think it does deliver. There are some quirks/wrinkles that may bite if you heavily require things like Qi's qi::locals<>
or switching skippers in recursive rules.
As long as you keep these in mind you'll find that X3 is a breeze to use compared to Qi, mostly due to core language integration (composability is the biggest win IMO).
You can have a scan through (my) boost-spirit-x3 answers on this site. (Not all answers are on questions tagged as such, so consider also searching for the text 'x3').
Development did not stop:
$ git log --all --oneline --decorate --date-order \
--after=2014-7-1 --graph -- include/boost/spirit/home/x3
* ea57c257f Prevent parse_nan() from dereferencing out of range iterator
* 1433de2fe X3: Remove unused function_types includes
* 5bd4d1061 X3: Dereference a single item view instead of unwrapping sequence
* 6cd3d3a08 fix sequence partitioning problem (reverted from commit a8e391bd99dddb3f9ece84bdb1bb9236b0a37cf7)
* 9bdbf6bd2 X3: Fixed iterator move_to to single item sequence
* c5411ad23 X3: Reenable fusion::map support
* 60031eb77 Fix container traits for msvc (#318)
* b10e4a477 Merge pull request #320 from think-cell/thinkcell_iterator_check
|\
* | 6de179282 If there's ambiguity in attribute_category on container_attribute or tuple_attribute (e.g. array and std::array), choose tuple_attribute. We probably should define is_container better.
| * 766cc4c9b ForwardIterator -> ReadableIteratorConcept & ForwardTraversalConcept
|/
* 52de6d17b Fix for trac ticket 12928 "x3 cannot synthesize attribute of type boost::iterator_range in a sequence parser"
* cb946ba08 X3: Fixed include guard names collision
* 5ec71cfd3 Merge pull request #307 from octopus-prime/optional_attribute
|\
* \ 1265ee169 Merge pull request #120 from mlang/x3/implicit
|\ \
* \ \ deab0a261 Merge pull request #109 from mlang/x3/repeat-kleene-auto
|\ \ \
* | | | 6d6f40c3e X3: Workaround VS2015 rvalue ref in template of noexcept expression bug
* | | | a30e517b1 X3: Workaround VS2015 decltype in function arguments bug
| | | * c3a83ce08 optional_attribute
| |_|/
|/| |
* | | b8b82630a fix x3::uint_parser<T(signed)> overflow problem
* | | 690830713 Replaced tab by spaces.
* | | 74f67517c Bugfix and tests for issue #287 "x3 cannot parse into associative containers anymore".
* | | ee4943d58 X3: Fix `unused_type` attribute case in `parse_into_container`
* | | 79995f7e8 x3::error_handler::position() CR+LF lines wrongly counted.
* | | b4e4762b6 Add noexcept specs to x3::variant and forward_ast
* | | 19972887f Context& -> Context const&
* | | 30dfb6230 simplify with directive (3): make rvalue injection mutable
* | | 361b12eee simplify with directive
* | | 1f513cb40 Revert "Crash when print attribute in debug mode."
* | | e7962ea67 Update simple_trace.hpp
* | | 8c7f9c071 Update and_predicate.hpp
* | | ca335f30f Fix dangling refs in debug of call_rule_defintion`
* | | cfa7446a8 silence unused parameter warning
* | | 16320a556 Check for unitialized rules in parser composition
* | | 6c1cab48f Avoid logic_error if rule was unitialized
* | | 29dc7ec6e Added BOOST_SPIRIT_NO_REAL_NUMBERS to not include float parsers
* | | 30c1d59d3 Make standard_wide and wchar_t optional for platforms that do not support
* | | 1d5620fef Update rule.hpp
* | | 379413a50 Fixed bug where string("string1") >> attr(std::string("string2")) produces the wrong attribute result
* | | 124fda502 fix wrong out commented parameter in x3::detail::make_rule_context(...)
* | | 8357037e8 use ignore_unused instead of C-cast to void
* | | a1a30d431 Suppress 'unused parameter' warnings in x3::parse_rule(...)
* | | 5c782ee5e Suppress 'unused parameter' warnings in x3::detail::make_unique_context(...)
* | | 672391030 Suppress 'unused parameter' warnings in x3::detail::move_if_not_alternative::call(...)
* | | 5b1a433d2 Suppress 'unused parameter' warnings in x3::detail::parse_into_container_base_impl::call(...)
* | | 10286fafa Suppress 'unused parameter' warnings in x3::detail::call(...)
* | | 96272e324 Suppress 'unused parameter' warnings in x3::get_info::operator()(...)
* | | 3063a043c Suppress 'unused parameter' warnings in x3::lazy_semantic_predicate::parse(...)
* | | ce02014df Suppress 'unused parameter' warnings in x3::attr_parser::parse(...)
* | | c3f97a461 Suppress 'unused parameter' warnings in rule.hpp
* | | 277cdf777 Suppress 'unused parameter' warnings in container_traits.hpp
* | | a19bcb5b7 Suppress an "unused parameter" warning of rule_
| | | * 8616d3ff3 Update exposed attribute for alternative parser
| |_|/
|/| |
* | | de81dc44d Using boost TTI library to replace hand-written TTI code.
* | | b818ca5c8 - added x3 variant test - added x3 variant, extended variant swap member function
* | | 76c57b600 call c.insert(iter, f, l) or c.inser(f, l) as appropriate depending on container type.
* | | 2085a9f50 dangling reference to attribute when BOOST_SPIRIT_X3_DEBUG is defined
* | | 9e488859d Fixes for ticket https://svn.boost.org/trac/boost/ticket/12094
* | | c447315c1 Use forward<T> as appropriate
* | | a077a4cae fixes problem with move_to
* | | 7690022b9 Bigfix: with_context should not return const context. doing so will introduce type conflicts and linker errors
* | | 82bd5b2cc fixes problem with BOOST_SPIRIT_X3_DEBUG.
* | | d98a7dc9f Merge pull request #175 from octopus-prime/develop
|\ \ \
| * | | a39923104 Use std::basic_string<Char> instead of Char*
* | | | 035fc0fd9 - added static assert on phrase_parse to make sure user does not pass in unused_type skipper - fixed symbols parser bug (fixes ticket 12016)
* | | | 3cee512a4 Merge pull request #170 from octopus-prime/develop
|\ \ \ \
| |/ / /
| * | | 8602d2b8e Replaced cend() by end().
| * | | 0037392a7 Changed push_back(unused_type, T const&) to push_back(unused_type, T&&).
* | | | a8e391bd9 fix sequence partitioning problem
* | | | d91cf7410 Fixes Ticket #11952
| * | | 9c2bc9f34 size calculation in has_reserve_method case only.
| * | | 1fbe050ef Replaced c.end() by c.cend(). Replaced std::integral_constant<bool, detail::has_reserve_method<Container>::value>() by typename detail::has_reserve_method<Container>::type{}.
| * | | 045216a5c Add and use has_reserve_method construct to determine whether container has reserve() method.
| * | | 27d3352ec Added reserve optimization for std::vector and std::basic_string
| * | | c014a081b Cleaned up container_traits.
|/ / /
* | | c31e79efa Using insert() method of containers in push_back().
* | | cec9817bc Added support for std::multimap, std::unordered_map and std::unordered_multimap.
* | | a362319f3 X3: fix char_range boundaries
* | | 2df3b8885 Merge pull request #110 from mlang/x3/error_handler.position_of
|\ \ \
* \ \ \ 949e49979 Merge pull request #132 from bebuch/develop
|\ \ \ \
* | | | | b42df6fe5 X3: Fix parse_sequence with variant_attribute.
| * | | | 5dadb838c return type via decltype(auto)
|/ / / /
* | | | 509029d24 remove include duplicate
* | | | 9b0daf9cc X3: Less is more.
* | | | d109f01de X3: We do not need integer_sequence.hpp.
* | | | 090e7a056 X3: Simplify operator>.
* | | | 391cbb2f2 X3: Use decltype instead of result_of.
* | | | c6aba10d5 Merge pull request #124 from mlang/x3/context/decltype-auto
|\ \ \ \
| * | | | d6b5f0d92 X3: Eliminate two more hidden cases of get_result.
* | | | | d87aa6846 X3: Add another missing const&.
|/ / / /
* | | | 20658b2b2 X3: Remove useless using-directives.
* | | | 6ede5f7c8 X3: [context] decltype(auto) makes get_result unnecessary.
| | | * 2f20512a3 X3: Make use of implicit constructibility.
| |_|/
|/| |
* | | 53352198f X3: Use inheritance instead of typedef typename ...::type type;
* | | af73c1c20 X3: Simplify alternative::parse.
* | | 1d7159ce0 X3: Avoid copying the arguments to {unary,binary}_parser, sequence and alternative.
* | | bc20650d9 X3: Remove unused include mpl/joint_view.hpp and add mpl/insert_range.hpp where appropriate.
* | | 2a94b18e9 X3: Fix push_back to mpl::view in x3::sequence.
| * | 2995de5fa Allow retrieval of the iterator_range of a position_tagged.
|/ /
| * c5b9823ae auto makes this simpler.
|/
* 0a7fadd83 Merge pull request #104 from teajay-fr/feature/x3_binary
|\
* | bec338319 Remove leftover pragma once
| * e1210dff4 Clean up and finalized the binary parser
* | 55e87419c c++11 coding style tweaks
* | 1c8d9b6e2 removing #pragma once clutter
| * d5f119779 Add support for the binary parsers
* | ad507e4da Fix include paths.
* | cea20165b - removing extensions - promoting stuff from extensions to directive
* | 10c13779b Rename {directive => extensions}/matches.hpp.
* | dc4c7f824 x3::matches.
|/
* 8bd4d7078 Add one space after 'for'.
* c13b91ac6 X3: No need for BOOST_FOREACH.
* 033e52c03 Make annotation.hpp generic and move to support/utility/annotate_on_success.hpp.
* 7404981b0 Use utf_to_utf in x3::error_handler.
* ac70d6f65 Allow rule.hpp to be included independently.
* 0debda097 Allow string/string_literal.hpp be able to be independently included.
* 20170960d bug fix x3: where we try to push_back to an mpl::view.
* c60d93fff bug fix for x3 where container attribute is substitute for the container value type. happens with recursive data structures such as vector<v> where v is a variant that also contains vector<v>.
* 0e17b6d05 reorganizing files into cleaner directory structures
* a3d667002 Making testing a full-fledged X3 suppoty utility
* c45fdad1b Bug fix: rule IDs must have accessible on_error and on_sucess
* 3627a4690 more test updates and cleanup
* 0adee06b2 cleaning up the tests
* 63e779a2e added version type
* 21dd555af Updated the check-for-self in x3::variant
* 14c87d616 specific support for puch_back and append to std::map
* c5fe8848c added explicit force_attribute bool template parameter to rule
* 5e4b0a7c8 X3 now works with g++4.9
* 2baddc5f2 fixed new symbols usage
* 729ffd680 Merge pull request #70 from mlang/error_reporting/without/line_pos_iterator
|\
* | c0ea389a1 Fix misplaced inline keyword.
| * 5d6dd28e8 Decouple error_reporting.hpp from line_pos_iterator.
* | 19ca8017b Add missing inline to avoid linker errors about duplicate definitions.
|/
* fec70d409 Merge branch 'x3-devel' into feature/x3_devlop_merge
|\
* | 9113f02e5 Macro to remove filesystem dependency
| * 6c0b5da3a Improved the formating
| * e4d195ef2 Merge branch 'x3-devel' of https://github.com/boostorg/spirit into feature/x3_no_case
| |\
| | * 92bd34bd7 Corrected the seperation of the literal string from their sizes in the any_char operator() Reactivated all the char set tests
| | * 7bde4c42f Add as_parser templates to handle on char strings as char_ instead of literal_string
| | * 134e30e75 Add support for char sets and char ranges
| | * a4e043101 Add the char_set and char_range parser
| | * eec3ff531 Fix the char encoding specific generators for all the string literal parsers
| * 1d6267610 Simplified the case sensitive/insensitive helpers
| * 60cca1161 Implement the no case directive for the symbols parser
| * ad9d0429a Use a less invasive case_compare type extraction from the context
| * 3f089ad13 Create a fresh no_case context for the skipper
| * 430cd5fee Add missing template keyword for clang
| * ea72c747a Make the char class parser no_case compatible. Make all no_case tests pass.
| * 1f01e9056 Use the same logic as the skipper to swap between case sensitive and case insensitive parsing.
| * c0dfd1416 Move the no case tag and the context extraction template to the support folder
| * 4b1fab071 Make no case directive compilable
| * 5a7495205 Add no case directive
* bcd6f561a Merge branch 'develop'
The last commit is in 2018.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With