Skip to content

Migrate all parsers from Boost.Spirit Qi to X3#7432

Merged
DennisOSRM merged 6 commits intomasterfrom
migrate-spirit-qi-to-x3
Apr 7, 2026
Merged

Migrate all parsers from Boost.Spirit Qi to X3#7432
DennisOSRM merged 6 commits intomasterfrom
migrate-spirit-qi-to-x3

Conversation

@DennisOSRM
Copy link
Copy Markdown
Collaborator

@DennisOSRM DennisOSRM commented Mar 26, 2026

This PR modernizes the parsing infrastructure across the entire codebase by migrating from Boost.Spirit Qi (V2) to the newer X3 library.

Benefits

  • Improved compile times: X3's header-only architecture with better template metaprogramming reduces compilation overhead
  • Modern C++ patterns: Replaces Phoenix bindings with C++ lambdas and grammar class hierarchies with namespace-based composition
  • AppleClang compatibility: Side-steps warnings from recent AppleClang versions that have tighter rules around casts and type conversions in Phoenix expressions

Changes

16 files migrated across the entire parser stack:

  • Server API parameter parsers (route, table, match, trip, nearest, tile)
  • URL parser (eliminated qi_iter_pos dependency)
  • ISO 8601 duration parser
  • CSV file parser
  • Opening hours parser (~35 rules, most complex migration)
  • Conditional restrictions parser

Compile time benchmark

To verify improvements in compile time, the following compilation runs were timed (single core, release build). They show a 6% improvement in single core compilation time, which seems like a good win.

qi X3 speedup
Apple M1 382.18s 361.1s 8%
Apple M4 Pro 233.5s 220.91s 6%
Core i7 (GCC) 1534.0s 1438s 6%

Testing

✅ All existing tests pass:

  • server-tests: 16/16
  • extractor-tests: all pass
  • updater-tests: 5/5

Technical Details

  • API grammars use x3::with<params_tag> context pattern instead of inherited attributes
  • Typed intermediate rules prevent variant<T,T> from same-type alternatives
  • Removed BOOST_SPIRIT_USE_PHOENIX_V3 and BOOST_PHOENIX_STL_TUPLE_H_ CMake defines

Total: 1018 insertions, 1010 deletions

This change modernizes the parsing infrastructure across the entire codebase
by migrating from Boost.Spirit Qi (V2) to the newer X3 library. This brings
several benefits:

- **Improved compile times**: X3's header-only architecture with better template
  metaprogramming reduces compilation overhead
- **Modern C++ patterns**: Replaces Phoenix bindings with C++ lambdas and grammar
  class hierarchies with namespace-based composition
- **AppleClang compatibility**: Side-steps warnings from recent AppleClang versions
  that have tighter rules around casts and type conversions in Phoenix expressions

Changes across 16 files:
- Server API parameter parsers (route, table, match, trip, nearest, tile)
- URL parser (eliminated qi_iter_pos dependency)
- ISO 8601 duration parser
- CSV file parser
- Opening hours parser (~35 rules, most complex migration)
- Conditional restrictions parser

All existing tests pass (server-tests: 16/16, extractor-tests, updater-tests: 5/5).

Technical notes:
- API grammars use x3::with<params_tag> context pattern instead of inherited attributes
- Typed intermediate rules prevent variant<T,T> from same-type alternatives
- Removed BOOST_SPIRIT_USE_PHOENIX_V3 and BOOST_PHOENIX_STL_TUPLE_H_ CMake defines

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 26, 2026 13:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR completes a broad migration of the project’s parsing infrastructure from Boost.Spirit Qi/Phoenix to Boost.Spirit X3, simplifying grammars and removing Phoenix/CMake workarounds.

Changes:

  • Migrates multiple parsers (server API parameters, URL parsing, opening_hours, conditional_restrictions, CSV, ISO 8601 duration) from Qi to X3.
  • Refactors server API parameter grammars to use X3 context (x3::with<params_tag>) for threading the parameters struct.
  • Removes Phoenix-related dependency defines from CMake.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/util/opening_hours.cpp Rewrites the opening_hours grammar using X3 rules/symbol tables and X3 actions.
src/util/conditional_restrictions.cpp Replaces Qi grammar with X3 rules for conditional restriction parsing.
src/updater/csv_source.cpp Switches CSV value/key parsing expressions from Qi parsers to X3 parsers.
include/updater/csv_file_parser.hpp Refactors CSVFilesParser to accept X3 parsers and parse via an injected X3 parse function.
src/server/api/url_parser.cpp Migrates URL parsing grammar to X3 and replaces iter_pos-based prefix tracking with a computed length.
src/server/api/parameters_parser.cpp Updates parameter parsing to X3 context-based parsing and swaps grammar entrypoints to root rules.
include/server/api/trip_parameter_grammar.hpp Rewrites Trip API query grammar as X3 rule composition and context writes.
include/server/api/tile_parameter_grammar.hpp Replaces Tile grammar with an X3 rule definition for TileParameters.
include/server/api/table_parameter_grammar.hpp Rewrites Table API query grammar using X3 symbols, typed rules, and context writes.
include/server/api/route_parameters_grammar.hpp Rewrites Route API query grammar using X3 symbols, typed rules, and context writes.
include/server/api/nearest_parameter_grammar.hpp Rewrites Nearest API query grammar as X3 rules and context writes.
include/server/api/match_parameter_grammar.hpp Rewrites Match API query grammar as X3 rules and context writes.
include/server/api/base_parameters_grammar.hpp Provides shared X3 primitives/options parsing with params_tag context threading.
include/extractor/raster_source.hpp Removes now-unneeded Qi includes.
include/extractor/extraction_helper_functions.hpp Migrates ISO 8601 duration parsing helpers from Qi to X3.
CMakeLists.txt Removes Phoenix-related Boost.Spirit/Phoenix workaround defines.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +401 to +403
inline const auto year_end_value = x3::rule<struct ye_tag, unsigned>{"year_end"} =
('-' >> year_val >> x3::omit[-('/' >> x3::uint_)]) |
(x3::lit('+') >> x3::attr(static_cast<unsigned>(-1)));
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

year_end_value uses x3::attr(static_cast<unsigned>(-1)) as the '+' sentinel, and later converts it to int for Monthday. Converting an out-of-range unsigned to int is implementation-defined and can yield an unintended large year instead of the intended -1 sentinel. Prefer making year_end_value an int (or directly synthesize oh::Monthday(-1) for '+') so the sentinel is represented safely and portably.

Suggested change
inline const auto year_end_value = x3::rule<struct ye_tag, unsigned>{"year_end"} =
('-' >> year_val >> x3::omit[-('/' >> x3::uint_)]) |
(x3::lit('+') >> x3::attr(static_cast<unsigned>(-1)));
inline const auto year_end_value = x3::rule<struct ye_tag, int>{"year_end"} =
('-' >> year_val >> x3::omit[-('/' >> x3::uint_)]) |
(x3::lit('+') >> x3::attr(-1));

Copilot uses AI. Check for mistakes.
Comment thread src/util/opening_hours.cpp
Comment thread src/util/conditional_restrictions.cpp
DennisOSRM and others added 3 commits March 26, 2026 14:56
When using a rule as a parser within an alternative in X3, the attribute
must be explicitly forwarded with a semantic action. The date_to rule
was not propagating the Monthday attribute from date_from, causing
date ranges to have empty 'to' fields.

This fixes all 14 opening_hours test failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use C++17 concatenated namespace syntax instead of nested namespace
declarations, as recommended by modernize-concat-nested-namespaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@DennisOSRM DennisOSRM requested a review from TheMarex March 26, 2026 16:16
Copy link
Copy Markdown
Member

@TheMarex TheMarex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good to me code wise, but I don't think X3 is an improvement in readability over Qi to be honest. You mention a compile time benchmark, but what would be really interesting here is actually a query time benchmark. scripts/osrm-runner.js should make that easy enough.

@DennisOSRM
Copy link
Copy Markdown
Collaborator Author

Ran benchmarks on today's germany-latest with a fixed set of 1000 random queries. The numbers between master and this branch are the same. The differences look like noise in the microsecond range per query.

@DennisOSRM DennisOSRM merged commit a72e463 into master Apr 7, 2026
23 checks passed
@DennisOSRM DennisOSRM deleted the migrate-spirit-qi-to-x3 branch April 7, 2026 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants